blob: b2b45723e2cd64028b06f622e555f18fcac08ba4 [file] [log] [blame]
/* linux/arch/arm/mach-msm/devices.c
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2007-2009 HTC Corporation.
* Author: Thomas Tsai <thomas_tsai@htc.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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 <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <mach/msm_iomap.h>
#include <mach/dma.h>
#include "gpio_chip.h"
#include "devices.h"
#include <mach/board.h>
#include <mach/board_htc.h>
#include <mach/msm_hsusb.h>
#include <linux/usb/mass_storage_function.h>
#include <linux/usb/android.h>
#include <asm/mach/flash.h>
#include <asm/setup.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
#include <linux/android_pmem.h>
#include <mach/msm_rpcrouter.h>
#include <mach/msm_iomap.h>
#include <asm/mach/mmc.h>
static char *df_serialno = "000000000000";
#if 0
struct platform_device *devices[] __initdata = {
&msm_device_nand,
&msm_device_smd,
&msm_device_i2c,
};
void __init msm_add_devices(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
}
#endif
#define HSUSB_API_INIT_PHY_PROC 2
#define HSUSB_API_PROG 0x30000064
#define HSUSB_API_VERS 0x10001
static void internal_phy_reset(void)
{
struct msm_rpc_endpoint *usb_ep;
int rc;
struct hsusb_phy_start_req {
struct rpc_request_hdr hdr;
} req;
printk(KERN_INFO "msm_hsusb_phy_reset\n");
usb_ep = msm_rpc_connect(HSUSB_API_PROG, HSUSB_API_VERS, 0);
if (IS_ERR(usb_ep)) {
printk(KERN_ERR "%s: init rpc failed! error: %ld\n",
__func__, PTR_ERR(usb_ep));
goto close;
}
rc = msm_rpc_call(usb_ep, HSUSB_API_INIT_PHY_PROC,
&req, sizeof(req), 5 * HZ);
if (rc < 0)
printk(KERN_ERR "%s: rpc call failed! (%d)\n", __func__, rc);
close:
msm_rpc_close(usb_ep);
}
/* adjust eye diagram, disable vbusvalid interrupts */
static int hsusb_phy_init_seq[] = { 0x40, 0x31, 0x1D, 0x0D, 0x1D, 0x10, -1 };
#ifdef CONFIG_USB_FUNCTION
static char *usb_functions[] = {
#if defined(CONFIG_USB_FUNCTION_MASS_STORAGE) || defined(CONFIG_USB_FUNCTION_UMS)
"usb_mass_storage",
#endif
#ifdef CONFIG_USB_FUNCTION_ADB
"adb",
#endif
};
static struct msm_hsusb_product usb_products[] = {
{
.product_id = 0x0c01,
.functions = 0x00000041, /* usb_mass_storage */
},
{
.product_id = 0x0c02,
.functions = 0x00000043, /* usb_mass_storage + adb */
},
};
#endif
struct msm_hsusb_platform_data msm_hsusb_pdata = {
.phy_reset = internal_phy_reset,
.phy_init_seq = hsusb_phy_init_seq,
#ifdef CONFIG_USB_FUNCTION
.vendor_id = 0x0bb4,
.product_id = 0x0c02,
.version = 0x0100,
.product_name = "Android Phone",
.manufacturer_name = "HTC",
.functions = usb_functions,
.num_functions = ARRAY_SIZE(usb_functions),
.products = usb_products,
.num_products = ARRAY_SIZE(usb_products),
#endif
};
#ifdef CONFIG_USB_FUNCTION
static struct usb_mass_storage_platform_data mass_storage_pdata = {
.nluns = 1,
.buf_size = 16384,
.vendor = "HTC ",
.product = "Android Phone ",
.release = 0x0100,
};
static struct platform_device usb_mass_storage_device = {
.name = "usb_mass_storage",
.id = -1,
.dev = {
.platform_data = &mass_storage_pdata,
},
};
#endif
#ifdef CONFIG_USB_ANDROID
static struct android_usb_platform_data android_usb_pdata = {
.vendor_id = 0x0bb4,
.product_id = 0x0c01,
.adb_product_id = 0x0c02,
.version = 0x0100,
.product_name = "Android Phone",
.manufacturer_name = "HTC",
.nluns = 1,
};
static struct platform_device android_usb_device = {
.name = "android_usb",
.id = -1,
.dev = {
.platform_data = &android_usb_pdata,
},
};
#endif
void __init msm_add_usb_devices(void (*phy_reset) (void))
{
/* setup */
if (phy_reset)
msm_hsusb_pdata.phy_reset = phy_reset;
msm_device_hsusb.dev.platform_data = &msm_hsusb_pdata;
platform_device_register(&msm_device_hsusb);
#ifdef CONFIG_USB_FUNCTION_MASS_STORAGE
platform_device_register(&usb_mass_storage_device);
#endif
#ifdef CONFIG_USB_ANDROID
platform_device_register(&android_usb_device);
#endif
}
static struct android_pmem_platform_data pmem_pdata = {
.name = "pmem",
.allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
.cached = 1,
};
static struct android_pmem_platform_data pmem_adsp_pdata = {
.name = "pmem_adsp",
.allocator_type = PMEM_ALLOCATORTYPE_BUDDYBESTFIT,
.cached = 0,
};
static struct android_pmem_platform_data pmem_camera_pdata = {
.name = "pmem_camera",
.allocator_type = PMEM_ALLOCATORTYPE_BUDDYBESTFIT,
.cached = 0,
};
static struct android_pmem_platform_data pmem_gpu0_pdata = {
.name = "pmem_gpu0",
.allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
.cached = 0,
.buffered = 1,
};
static struct android_pmem_platform_data pmem_gpu1_pdata = {
.name = "pmem_gpu1",
.allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
.cached = 0,
.buffered = 1,
};
static struct platform_device pmem_device = {
.name = "android_pmem",
.id = 0,
.dev = { .platform_data = &pmem_pdata },
};
static struct platform_device pmem_adsp_device = {
.name = "android_pmem",
.id = 1,
.dev = { .platform_data = &pmem_adsp_pdata },
};
static struct platform_device pmem_gpu0_device = {
.name = "android_pmem",
.id = 2,
.dev = { .platform_data = &pmem_gpu0_pdata },
};
static struct platform_device pmem_gpu1_device = {
.name = "android_pmem",
.id = 3,
.dev = { .platform_data = &pmem_gpu1_pdata },
};
static struct platform_device pmem_camera_device = {
.name = "android_pmem",
.id = 4,
.dev = { .platform_data = &pmem_camera_pdata },
};
static struct resource ram_console_resource[] = {
{
.flags = IORESOURCE_MEM,
}
};
static struct platform_device ram_console_device = {
.name = "ram_console",
.id = -1,
.num_resources = ARRAY_SIZE(ram_console_resource),
.resource = ram_console_resource,
};
void __init msm_add_mem_devices(struct msm_pmem_setting *setting)
{
if (setting->pmem_size) {
pmem_pdata.start = setting->pmem_start;
pmem_pdata.size = setting->pmem_size;
platform_device_register(&pmem_device);
}
if (setting->pmem_adsp_size) {
pmem_adsp_pdata.start = setting->pmem_adsp_start;
pmem_adsp_pdata.size = setting->pmem_adsp_size;
platform_device_register(&pmem_adsp_device);
}
if (setting->pmem_gpu0_size) {
pmem_gpu0_pdata.start = setting->pmem_gpu0_start;
pmem_gpu0_pdata.size = setting->pmem_gpu0_size;
platform_device_register(&pmem_gpu0_device);
}
if (setting->pmem_gpu1_size) {
pmem_gpu1_pdata.start = setting->pmem_gpu1_start;
pmem_gpu1_pdata.size = setting->pmem_gpu1_size;
platform_device_register(&pmem_gpu1_device);
}
if (setting->pmem_camera_size) {
pmem_camera_pdata.start = setting->pmem_camera_start;
pmem_camera_pdata.size = setting->pmem_camera_size;
platform_device_register(&pmem_camera_device);
}
if (setting->ram_console_size) {
ram_console_resource[0].start = setting->ram_console_start;
ram_console_resource[0].end = setting->ram_console_start
+ setting->ram_console_size - 1;
platform_device_register(&ram_console_device);
}
}
#define PM_LIBPROG 0x30000061
#if (CONFIG_MSM_AMSS_VERSION == 6220) || (CONFIG_MSM_AMSS_VERSION == 6225)
#define PM_LIBVERS 0xfb837d0b
#else
#define PM_LIBVERS 0x10001
#endif
#if 0
static struct platform_device *msm_serial_devices[] __initdata = {
&msm_device_uart1,
&msm_device_uart2,
&msm_device_uart3,
#ifdef CONFIG_SERIAL_MSM_HS
&msm_device_uart_dm1,
&msm_device_uart_dm2,
#endif
};
int __init msm_add_serial_devices(unsigned num)
{
if (num > MSM_SERIAL_NUM)
return -EINVAL;
return platform_device_register(msm_serial_devices[num]);
}
#endif
#define ATAG_SMI 0x4d534D71
/* setup calls mach->fixup, then parse_tags, parse_cmdline
* We need to setup meminfo in mach->fixup, so this function
* will need to traverse each tag to find smi tag.
*/
int __init parse_tag_smi(const struct tag *tags)
{
int smi_sz = 0, find = 0;
struct tag *t = (struct tag *)tags;
for (; t->hdr.size; t = tag_next(t)) {
if (t->hdr.tag == ATAG_SMI) {
printk(KERN_DEBUG "find the smi tag\n");
find = 1;
break;
}
}
if (!find)
return -1;
printk(KERN_DEBUG "parse_tag_smi: smi size = %d\n", t->u.mem.size);
smi_sz = t->u.mem.size;
return smi_sz;
}
__tagtable(ATAG_SMI, parse_tag_smi);
#define ATAG_HWID 0x4d534D72
int __init parse_tag_hwid(const struct tag *tags)
{
int hwid = 0, find = 0;
struct tag *t = (struct tag *)tags;
for (; t->hdr.size; t = tag_next(t)) {
if (t->hdr.tag == ATAG_HWID) {
printk(KERN_DEBUG "find the hwid tag\n");
find = 1;
break;
}
}
if (find)
hwid = t->u.revision.rev;
printk(KERN_DEBUG "parse_tag_hwid: hwid = 0x%x\n", hwid);
return hwid;
}
__tagtable(ATAG_HWID, parse_tag_hwid);
#define ATAG_SKUID 0x4d534D73
int __init parse_tag_skuid(const struct tag *tags)
{
int skuid = 0, find = 0;
struct tag *t = (struct tag *)tags;
for (; t->hdr.size; t = tag_next(t)) {
if (t->hdr.tag == ATAG_SKUID) {
printk(KERN_DEBUG "find the skuid tag\n");
find = 1;
break;
}
}
if (find)
skuid = t->u.revision.rev;
printk(KERN_DEBUG "parse_tag_skuid: hwid = 0x%x\n", skuid);
return skuid;
}
__tagtable(ATAG_SKUID, parse_tag_skuid);
#define ATAG_ENGINEERID 0x4d534D75
int __init parse_tag_engineerid(const struct tag *tags)
{
int engineerid = 0, find = 0;
struct tag *t = (struct tag *)tags;
for (; t->hdr.size; t = tag_next(t)) {
if (t->hdr.tag == ATAG_ENGINEERID) {
printk(KERN_DEBUG "find the engineer tag\n");
find = 1;
break;
}
}
if (find)
engineerid = t->u.revision.rev;
printk(KERN_DEBUG "parse_tag_engineerid: hwid = 0x%x\n", engineerid);
return engineerid;
}
__tagtable(ATAG_ENGINEERID, parse_tag_engineerid);
static int mfg_mode;
int __init board_mfg_mode_init(char *s)
{
if (!strcmp(s, "normal"))
mfg_mode = 0;
else if (!strcmp(s, "factory2"))
mfg_mode = 1;
else if (!strcmp(s, "recovery"))
mfg_mode = 2;
else if (!strcmp(s, "charge"))
mfg_mode = 3;
return 1;
}
__setup("androidboot.mode=", board_mfg_mode_init);
int board_mfg_mode(void)
{
return mfg_mode;
}
static int __init board_serialno_setup(char *serialno)
{
char *str;
if (board_mfg_mode() || !strlen(serialno))
str = df_serialno;
else
str = serialno;
#ifdef CONFIG_USB_FUNCTION
msm_hsusb_pdata.serial_number = str;
#endif
#ifdef CONFIG_USB_ANDROID
android_usb_pdata.serial_number = str;
#endif
return 1;
}
__setup("androidboot.serialno=", board_serialno_setup);