blob: 6ce49509a4bb375546030623cd6a514e94b7c836 [file] [log] [blame]
/*
* Atheros CUS227 board support
*
* Copyright (c) 2013 The Linux Foundation. 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 <linux/pci.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/ath9k_platform.h>
#include <linux/ar8216_platform.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/mtd/mtd.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <asm/mach-ath79/ar71xx_regs.h>
#include <asm/mach-ath79/ath79.h>
#include <linux/of_platform.h>
#include "common.h"
#include "dev-ap9x-pci.h"
#include "dev-audio.h"
#include "dev-eth.h"
#include "dev-gpio-buttons.h"
#include "dev-leds-gpio.h"
#include "dev-m25p80.h"
#include "dev-nand.h"
#include "dev-spi.h"
#include "dev-usb.h"
#include "dev-wmac.h"
#include "dev-i2c.h"
#include "machtypes.h"
#include "nand-caldata-fixup.h"
#define CUS227_GPIO_S1 12
#define CUS227_GPIO_S2 13
#define CUS227_GPIO_S3 14
#define CUS227_GPIO_S4 15
#define CUS227_GPIO_I2C_SDA 16
#define CUS227_GPIO_I2C_SCL 17
#define CUS227_KEYS_POLL_INTERVAL 20 /* msecs */
#define CUS227_KEYS_DEBOUNCE_INTERVAL (3 * CUS227_KEYS_POLL_INTERVAL)
#define CUS227_GPIO_SPI_CLK 6
#define CUS227_GPIO_SPI_MOSI 7
#define CUS227_GPIO_SPI_MISO 8
#define CUS227_GPIO_I2S_MCLK 22
#define CUS227_GPIO_I2S_SD 18
#define CUS227_GPIO_I2S_WS 20
#define CUS227_GPIO_I2S_CLK 21
#define CUS227_GPIO_I2S_MIC_SD 19
#define CUS227_GPIO_SPDIF_OUT 4
#define CUS227_GPIO_SPI_CS1 11
#define CUS227_MAC0_OFFSET 0
#define CUS227_WMAC_CALDATA_OFFSET 0x1000
static struct ath79_caldata_fixup cus227_caldata = {
.name = "art",
.wmac_caldata_addr = CUS227_WMAC_CALDATA_OFFSET,
.pcie_caldata_addr = { FIXUP_UNDEFINED, FIXUP_UNDEFINED },
.mac_addr = { FIXUP_UNDEFINED, CUS227_MAC0_OFFSET },
};
static struct of_device_id __initdata cus227_common_ids[] = {
{ .type = "soc", },
{ .compatible = "gpio-keys", },
{ .compatible = "gpio-leds", },
{},
};
/* There is no H/W I2C controller in ATH79 SoCs, so use GPIO based S/W I2C master */
static struct i2c_gpio_platform_data ath79_i2c_gpio_data = {
.sda_pin = CUS227_GPIO_I2C_SDA,
.scl_pin = CUS227_GPIO_I2C_SCL,
};
/* Because CUS227 doesn't have a NOR flash on the SPI bus, we cannot
* reuse the routines from dev-m25p80.c to instanciate it.
* That's also the reason why the first device on the bus is 1 and not 0 */
static struct ath79_spi_controller_data ath79_spi1_cdata =
{
.cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
.is_flash = false,
.cs_line = 1,
};
static struct spi_board_info cus227_spi_info[] = {
{
.bus_num = 0,
.chip_select = 1,
.max_speed_hz = 25000000,
.modalias = "wm8988",
.controller_data = &ath79_spi1_cdata,
}
};
static void __init cus227_audio_setup(void)
{
u32 t;
/* Reset I2S internal controller */
t = ath79_reset_rr(AR71XX_RESET_REG_RESET_MODULE);
ath79_reset_wr(AR71XX_RESET_REG_RESET_MODULE, t | AR934X_RESET_I2S );
udelay(1);
/* GPIO configuration
Please note that the value in direction_output doesn't really matter
here as GPIOs are configured to relay internal data signal
*/
gpio_request(CUS227_GPIO_I2S_CLK, "I2S CLK");
ath79_gpio_output_select(CUS227_GPIO_I2S_CLK, AR934X_GPIO_OUT_MUX_I2S_CLK);
gpio_direction_output(CUS227_GPIO_I2S_CLK, 0);
gpio_request(CUS227_GPIO_I2S_WS, "I2S WS");
ath79_gpio_output_select(CUS227_GPIO_I2S_WS, AR934X_GPIO_OUT_MUX_I2S_WS);
gpio_direction_output(CUS227_GPIO_I2S_WS, 0);
gpio_request(CUS227_GPIO_I2S_SD, "I2S SD");
ath79_gpio_output_select(CUS227_GPIO_I2S_SD, AR934X_GPIO_OUT_MUX_I2S_SD);
gpio_direction_output(CUS227_GPIO_I2S_SD, 0);
gpio_request(CUS227_GPIO_I2S_MCLK, "I2S MCLK");
ath79_gpio_output_select(CUS227_GPIO_I2S_MCLK, AR934X_GPIO_OUT_MUX_I2S_MCK);
gpio_direction_output(CUS227_GPIO_I2S_MCLK, 0);
gpio_request(CUS227_GPIO_SPDIF_OUT, "SPDIF OUT");
ath79_gpio_output_select(CUS227_GPIO_SPDIF_OUT, AR934X_GPIO_OUT_MUX_SPDIF_OUT);
gpio_direction_output(CUS227_GPIO_SPDIF_OUT, 0);
gpio_request(CUS227_GPIO_I2S_MIC_SD, "I2S MIC_SD");
ath79_gpio_input_select(CUS227_GPIO_I2S_MIC_SD, AR934X_GPIO_IN_MUX_I2S_MIC_SD);
gpio_direction_input(CUS227_GPIO_I2S_MIC_SD);
/* Init stereo block registers in default configuration */
ath79_audio_setup();
}
static void __init cus227_register_i2c_devices(
struct i2c_board_info const *info)
{
ath79_register_i2c(&ath79_i2c_gpio_data, info, info?1:0);
}
static void __init cus227_register_spi_devices(
struct spi_board_info const *info)
{
gpio_request(CUS227_GPIO_SPI_CLK, "SPI CLK");
ath79_gpio_output_select(CUS227_GPIO_SPI_CLK, AR934X_GPIO_OUT_MUX_SPI_CLK);
gpio_direction_output(CUS227_GPIO_SPI_CLK, 0);
gpio_request(CUS227_GPIO_SPI_MOSI, "SPI MOSI");
ath79_gpio_output_select(CUS227_GPIO_SPI_MOSI, AR934X_GPIO_OUT_MUX_SPI_MOSI);
gpio_direction_output(CUS227_GPIO_SPI_MOSI, 0);
gpio_request(CUS227_GPIO_SPI_CS1, "SPI CS1");
ath79_gpio_output_select(CUS227_GPIO_SPI_CS1, AR934X_GPIO_OUT_MUX_SPI_CS1);
gpio_direction_output(CUS227_GPIO_SPI_CS1, 0);
/* a dedicated GPIO pin is used as SPI MISO since SPI controller doesn't support modes other than mode-0 */
gpio_request(CUS227_GPIO_SPI_MISO, "SPI MISO");
ath79_gpio_input_select(CUS227_GPIO_SPI_MISO, AR934X_GPIO_IN_MUX_SPI_MISO);
gpio_direction_input(CUS227_GPIO_SPI_MISO);
ath79_spi_data.bus_num = 0;
ath79_spi_data.num_chipselect = 2;
ath79_spi_data.miso_line = CUS227_GPIO_SPI_MISO;
ath79_register_spi(&ath79_spi_data, info, 1);
}
static void __init cus227_setup(void)
{
of_platform_bus_probe(NULL, cus227_common_ids, NULL);
ath79_register_usb();
ath79_register_nand();
ath79_mtd_caldata_fixup(&cus227_caldata);
/* just define GPIO based S/W I2C master device now */
/* later I2C slave devices can be added per platform defined */
cus227_register_i2c_devices(NULL);
cus227_register_spi_devices(cus227_spi_info);
ath79_register_wmac(NULL, NULL);
/* GMAC1 is connected to the internal switch */
ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII;
ath79_eth1_data.speed = SPEED_1000;
ath79_eth1_data.duplex = DUPLEX_FULL;
ath79_register_mdio(1, 0x0);
ath79_register_eth(1);
/* Audio initialization: PCM/I2S and CODEC */
cus227_audio_setup();
ath79_audio_device_register();
}
MIPS_MACHINE(ATH79_MACH_CUS227, "CUS227", "Qualcomm Atheros CUS227",
cus227_setup);