From 59c86b913d42df170a4a3b9fb31790beb0053572 Mon Sep 17 00:00:00 2001
From: Ashokkumar G <0xfee1dead.sa@gmail.com>
Date: Mon, 15 Jul 2013 17:06:08 -0600
Subject: [PATCH] GPLUGD: Adding gplugd peripheral changes and fixing clock
 issues due to changes in pxa gpio and marvell usb drivers

Signed-off-by: Ashokkumar G <0xfee1dead.sa@gmail.com>
---
 arch/arm/mach-mmp/gplugd.c     | 217 ++++++++++++++++++++++++++++++++++++++++-
 drivers/clk/mmp/clk-pxa168.c   |  17 +++-
 drivers/mmc/host/sdhci-pxav2.c |  17 ++++
 3 files changed, 244 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index d81b247..c6fc4fa 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -12,9 +12,14 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/gpio-pxa.h>
+#include <linux/mmc/sdhci.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/delay.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <asm/system.h>
 
 #include <mach/irqs.h>
 #include <mach/pxa168.h>
@@ -133,8 +138,31 @@
 	.irq_base	= MMP_GPIO_TO_IRQ(0),
 };
 
+#if 0
+static unsigned long mmc4_pin_config[] __initdata = {
+	GPIO125_MMC4_DAT3,
+	GPIO126_MMC4_DAT2,
+	GPIO127_MMC4_DAT1,
+	GPIO0_2_MMC4_DAT0,
+	GPIO1_2_MMC4_CMD,
+	GPIO2_2_MMC4_CLK,
+	GPIO113_GPIO
+};
+#endif
+static struct i2c_pxa_platform_data i2c_info __initdata = {
+	.use_pio	= 1,
+};
+
 static struct i2c_board_info gplugd_i2c_board_info[] = {
 	{
+		.type = "tda998X",
+		.addr = 0x70,
+	},
+	{
+		.type = "tda99Xcec",
+		.addr = 0x34,
+	},
+	{
 		.type = "isl1208",
 		.addr = 0x6F,
 	}
@@ -161,6 +189,10 @@ struct pxa168_eth_platform_data gplugd_eth_platform_data = {
 	.init        = gplugd_eth_init,
 };
 
+struct sdhci_pxa_platdata gplugd_sdh_platdata = {
+	.quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_NO_BUSY_IRQ | SDHCI_QUIRK_32BIT_DMA_SIZE,
+};
+
 static void __init select_disp_freq(void)
 {
 	/* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */
@@ -181,21 +213,198 @@ static void __init select_disp_freq(void)
 	}
 }
 
+#ifdef CONFIG_USB_SUPPORT
+
+#if defined(CONFIG_USB_EHCI_HCD) && defined(CONFIG_USB_EHCI_MV)
+
+static char *pxa168_u2h_clock_name[] = {
+	[0] = "U2HCLK",
+};
+
+static struct mv_usb_platform_data pxa168_u2h_pdata = {
+	/*.clknum         = 1,
+	.clkname        = pxa168_u2h_clock_name,*/
+	.mode           = MV_USB_MODE_HOST,
+	.phy_init       = pxa_usb_phy_init,
+	.phy_deinit     = pxa_usb_phy_deinit,
+	.set_vbus       = NULL,
+};
+#endif
+
+#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
+static char *pxa168_u2o_clock_name[] = {
+	[0] = "U2OCLK",
+};
+
+static struct mv_usb_platform_data pxa168_u2o_udc_pdata = {
+	/*.clknum			= 1,
+	.clkname		= pxa168_u2o_clock_name,*/
+	.vbus			= NULL,
+	.mode			= MV_USB_MODE_OTG,
+	.otg_force_a_bus_req	= 1,
+	.phy_init		= pxa_usb_phy_init,
+	.phy_deinit		= pxa_usb_phy_deinit,
+	.set_vbus		= NULL,
+};
+static struct mv_usb_platform_data pxa168_u2o_pdata = {
+	/*.clknum			= 1,
+	.clkname		= pxa168_u2o_clock_name,*/
+	.vbus			= NULL,
+	.mode			= MV_USB_MODE_OTG,
+	.otg_force_a_bus_req	= 1,
+	.phy_init		= pxa_usb_phy_init,
+	.phy_deinit		= pxa_usb_phy_deinit,
+	.set_vbus		= NULL,
+};
+static struct mv_usb_platform_data pxa168_u2o_otg_pdata = {
+	/*.clknum			= 1,
+	.clkname		= pxa168_u2o_clock_name,*/
+	.vbus			= NULL,
+	.mode			= MV_USB_MODE_OTG,
+	.otg_force_a_bus_req	= 1,
+	.phy_init		= pxa_usb_phy_init,
+	.phy_deinit		= pxa_usb_phy_deinit,
+	/*.set_vbus		= gplugd_u2o_vbus_set,*/
+	.set_vbus		= NULL,
+};
+
+#endif
+#endif
+
+static struct pxa2xx_spi_master pxa_ssp_master_info = {
+	.num_chipselect	= 1,
+	.enable_dma = 1,
+};
+
+static struct pxa2xx_spi_chip AT45DB041D_spi_info = {
+	.tx_threshold = 1,
+	.rx_threshold = 1,
+	.timeout = 1000,
+	.gpio_cs = 110
+};
+
+static struct spi_board_info __initdata gplugD_spi_board_info[] = {
+	{
+		.modalias = "mtd_dataflash",
+		.mode = SPI_MODE_0,
+		.max_speed_hz = 260000,
+		.bus_num = 2,
+		.chip_select = 0,
+		.platform_data = NULL,
+		.controller_data = &AT45DB041D_spi_info,
+		.irq = -1,
+	},
+};
+
+static inline int pxa168_add_spi(int id, struct pxa2xx_spi_master *pdata)
+{
+	struct platform_device *pd;
+
+	pd = platform_device_alloc("pxa2xx-spi", id);
+	if (pd == NULL) {
+		pr_err("pxa2xx-spi: failed to allocate device (id=%d)\n", id);
+		return -ENOMEM;
+	}
+
+	platform_device_add_data(pd, pdata, sizeof(*pdata));
+
+	return platform_device_add(pd);
+}
+
+static void __init read_store_mac_addr(void)
+{
+	int i;
+	u8 *mac_addr = gplugd_eth_platform_data.mac_addr;
+
+	/* gplugD uses serial number tag to pass MAC address */
+	*mac_addr++ = (system_serial_high >> 8) & 0xff;
+	*mac_addr++ = system_serial_high & 0xff;
+
+	for (i = 3; i >= 0; i--)
+		*mac_addr++ = (system_serial_low >> i*8) & 0xff;
+	/*printk(KERN_NOTICE "mac-address at gplugd.c is ");
+	for(i = 0; i < 6; i++)
+		printk(KERN_NOTICE "%c:", (pxa168_eth_data.mac_addr[i]));
+	for(i = 0; i < 6; i++)
+		printk(KERN_NOTICE "%d:", (pxa168_eth_data.mac_addr[i]));*/
+}
+
+static struct fb_videomode video_modes[] = {
+	/* TDA9989 Video Mode */
+	[0] = {
+		.pixclock	= 13468,
+		.refresh	= 60,
+		.xres		= 1280,
+		.yres		= 720,
+		.hsync_len	= 40,
+		.left_margin	= 220,
+		.right_margin	= 110,
+		.vsync_len	= 5,
+		.upper_margin	= 20,
+		.lower_margin	= 5,
+		.sync		= 0,
+	},
+};
+
+static struct pxa168fb_mach_info tda9981_hdmi_info __initdata = {
+	.id			= "tda9981",
+	.modes			= video_modes,
+	.num_modes		= ARRAY_SIZE(video_modes),
+	.pix_fmt		= PIX_FMT_RGB565,
+	.io_pin_allocation_mode	= PIN_MODE_DUMB_24,
+	.dumb_mode		= DUMB_MODE_RGB888,
+	.active			= 1,
+	.panel_rbswap		= 1,
+	.invert_pixclock	= 0,
+	.max_fb_size	    = (1280 * 720 * 4),
+};
+
 static void __init gplugd_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(gplugd_pin_config));
+	platform_device_add_data(&pxa168_device_gpio, &pxa168_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
+	platform_device_register(&pxa168_device_gpio);
 
 	select_disp_freq();
 
 	/* on-chip devices */
 	pxa168_add_uart(3);
 	pxa168_add_ssp(1);
-	pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
-	platform_device_add_data(&pxa168_device_gpio, &pxa168_gpio_pdata,
-				 sizeof(struct pxa_gpio_platform_data));
-	platform_device_register(&pxa168_device_gpio);
+	/*pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));*/
+	pxa168_add_twsi(0, &i2c_info, ARRAY_AND_SIZE(gplugd_i2c_board_info));
+
+	read_store_mac_addr();
 
 	pxa168_add_eth(&gplugd_eth_platform_data);
+	pxa168_add_sdh(1, &gplugd_sdh_platdata);
+	pxa168_add_sdh(2, &gplugd_sdh_platdata);
+
+#if defined(CONFIG_USB_EHCI_HCD) && defined(CONFIG_USB_EHCI_MV)
+	pxa168_device_u2h.dev.platform_data = &pxa168_u2h_pdata;
+	platform_device_register(&pxa168_device_u2h);
+#endif
+#ifdef CONFIG_USB_MV_UDC
+	pxa168_device_u2o.dev.platform_data = &pxa168_u2o_udc_pdata;
+	platform_device_register(&pxa168_device_u2o);
+#endif
+
+#ifdef CONFIG_USB_EHCI_MV_U2O
+	pxa168_device_u2oehci.dev.platform_data = &pxa168_u2o_pdata;
+	platform_device_register(&pxa168_device_u2oehci);
+#endif
+
+#if 0
+#ifdef CONFIG_USB_MV_OTG
+	pxa168_device_u2ootg.dev.platform_data = &pxa168_u2o_otg_pdata;
+	platform_device_register(&pxa168_device_u2ootg);
+#endif
+#endif
+	pxa168_add_ssp(2);
+	pxa168_add_spi(2, &pxa_ssp_master_info);
+	spi_register_board_info(gplugD_spi_board_info, ARRAY_SIZE(gplugD_spi_board_info));
+	pxa168_add_fb(&tda9981_hdmi_info);
+	pxa168_add_fb_ovly(&tda9981_hdmi_info);
 }
 
 MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 321a9ed..21a997e 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -662,7 +662,7 @@ void __init pxa168_clk_init(void)
 
 	clk = mmp_clk_register_apbc("gpio", "vctcxo",
 				apbc_base + APBC_GPIO, 10, 0, &clk_lock);
-	clk_register_clkdev(clk, NULL, "pxa-gpio");
+	clk_register_clkdev(clk, NULL, "mmp-gpio");
 
 	clk = mmp_clk_register_apbc("kpc", "clk32",
 				apbc_base + APBC_KPC, 10, 0, &clk_lock);
@@ -798,13 +798,24 @@ void __init pxa168_clk_init(void)
 	clk_register_clkdev(clk, "sph_clk", NULL);
 #endif
 
-	clk = mmp_clk_register_apmu("sph", "U2HCLK", apmu_base + APMU_USB,
+	/*clk = mmp_clk_register_apmu("sph", "U2HCLK", apmu_base + APMU_USB,
 				0x12, &clk_lock);
 	clk_register_clkdev(clk, "U2HCLK", NULL);
 
 	clk = mmp_clk_register_apmu("usb", "U2OCLK", apmu_base + APMU_USB,
 				0x09, &clk_lock);
-	clk_register_clkdev(clk, "U2OCLK", NULL);
+	clk_register_clkdev(clk, "U2OCLK", NULL);*/
+
+	clk = mmp_clk_register_apmu("sph", "pxa-sph", apmu_base + APMU_USB,
+				0x12, &clk_lock);
+	/*clk_register_clkdev(clk, "pxa-sph", NULL);*/
+	clk_register_clkdev(clk, NULL, "pxa-sph");
+
+	clk = mmp_clk_register_apmu("usb", "pxa-u2oehci", apmu_base + APMU_USB,
+				0x09, &clk_lock);
+	/*clk_register_clkdev(clk, "pxa-u2oehci", NULL);*/
+	clk_register_clkdev(clk, NULL, "pxa-u2oehci");
+
 
 #if 0
 	/*Check USB clock start*/
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 6a3f702..78ac2bc 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -111,7 +111,24 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
 	return 0;
 }
 
+/*
+ * we cannot talk to controller for 8 bus cycles according to sdio spec
+ * at lowest speed this is 100,000 HZ per cycle or 800,000 cycles
+ * which is quite a LONG TIME on a fast cpu -- so delay if needed
+ */
+static inline u16 pxa168_readw(struct sdhci_host *host, int reg)
+{
+	u32 temp;
+	if (reg == SDHCI_HOST_VERSION) {
+		temp = readl (host->ioaddr + SDHCI_HOST_VERSION - 2) >> 16;
+		return temp & 0xffff;
+	}
+
+	return readw(host->ioaddr + reg);
+}
+
 static const struct sdhci_ops pxav2_sdhci_ops = {
+	.read_w = &pxa168_readw,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.platform_reset_exit = pxav2_set_private_registers,
 	.platform_bus_width = pxav2_mmc_set_width,
-- 
1.8.1.6