505 lines
11 KiB
C
505 lines
11 KiB
C
/* 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/android_composite.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 MSM_RPC_VERS(1,1)
|
|
|
|
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 };
|
|
|
|
struct msm_hsusb_platform_data msm_hsusb_pdata = {
|
|
.phy_reset = internal_phy_reset,
|
|
.phy_init_seq = hsusb_phy_init_seq,
|
|
.usb_connected = notify_usb_connected,
|
|
};
|
|
|
|
static struct usb_mass_storage_platform_data mass_storage_pdata = {
|
|
.nluns = 1,
|
|
.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,
|
|
},
|
|
};
|
|
|
|
#ifdef CONFIG_USB_ANDROID_RNDIS
|
|
static struct usb_ether_platform_data rndis_pdata = {
|
|
/* ethaddr is filled by board_serialno_setup */
|
|
.vendorID = 0x0bb4,
|
|
.vendorDescr = "HTC",
|
|
};
|
|
|
|
static struct platform_device rndis_device = {
|
|
.name = "rndis",
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &rndis_pdata,
|
|
},
|
|
};
|
|
#endif
|
|
|
|
static char *usb_functions_ums[] = {
|
|
"usb_mass_storage",
|
|
};
|
|
|
|
static char *usb_functions_ums_adb[] = {
|
|
"usb_mass_storage",
|
|
"adb",
|
|
};
|
|
|
|
static char *usb_functions_rndis[] = {
|
|
"rndis",
|
|
};
|
|
|
|
static char *usb_functions_rndis_adb[] = {
|
|
"rndis",
|
|
"adb",
|
|
};
|
|
|
|
static char *usb_functions_all[] = {
|
|
#ifdef CONFIG_USB_ANDROID_RNDIS
|
|
"rndis",
|
|
#endif
|
|
"usb_mass_storage",
|
|
"adb",
|
|
#ifdef CONFIG_USB_ANDROID_ACM
|
|
"acm",
|
|
#endif
|
|
};
|
|
|
|
static struct android_usb_product usb_products[] = {
|
|
{
|
|
.product_id = 0x0c01,
|
|
.num_functions = ARRAY_SIZE(usb_functions_ums),
|
|
.functions = usb_functions_ums,
|
|
},
|
|
{
|
|
.product_id = 0x0c02,
|
|
.num_functions = ARRAY_SIZE(usb_functions_ums_adb),
|
|
.functions = usb_functions_ums_adb,
|
|
},
|
|
{
|
|
.product_id = 0x0ffe,
|
|
.num_functions = ARRAY_SIZE(usb_functions_rndis),
|
|
.functions = usb_functions_rndis,
|
|
},
|
|
{
|
|
.product_id = 0x0ffc,
|
|
.num_functions = ARRAY_SIZE(usb_functions_rndis_adb),
|
|
.functions = usb_functions_rndis_adb,
|
|
},
|
|
};
|
|
|
|
static struct android_usb_platform_data android_usb_pdata = {
|
|
.vendor_id = 0x0bb4,
|
|
.product_id = 0x0c01,
|
|
.version = 0x0100,
|
|
.product_name = "Android Phone",
|
|
.manufacturer_name = "HTC",
|
|
.num_products = ARRAY_SIZE(usb_products),
|
|
.products = usb_products,
|
|
.num_functions = ARRAY_SIZE(usb_functions_all),
|
|
.functions = usb_functions_all,
|
|
};
|
|
|
|
static struct platform_device android_usb_device = {
|
|
.name = "android_usb",
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &android_usb_pdata,
|
|
},
|
|
};
|
|
|
|
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_ANDROID_RNDIS
|
|
platform_device_register(&rndis_device);
|
|
#endif
|
|
platform_device_register(&usb_mass_storage_device);
|
|
platform_device_register(&android_usb_device);
|
|
}
|
|
|
|
static struct android_pmem_platform_data pmem_pdata = {
|
|
.name = "pmem",
|
|
.no_allocator = 1,
|
|
.cached = 1,
|
|
};
|
|
|
|
static struct android_pmem_platform_data pmem_adsp_pdata = {
|
|
.name = "pmem_adsp",
|
|
.no_allocator = 0,
|
|
.cached = 0,
|
|
};
|
|
|
|
static struct android_pmem_platform_data pmem_camera_pdata = {
|
|
.name = "pmem_camera",
|
|
.no_allocator = 1,
|
|
.cached = 0,
|
|
};
|
|
|
|
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_camera_device = {
|
|
.name = "android_pmem",
|
|
.id = 2,
|
|
.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,
|
|
};
|
|
|
|
static struct resource resources_hw3d[] = {
|
|
{
|
|
.start = 0xA0000000,
|
|
.end = 0xA00fffff,
|
|
.flags = IORESOURCE_MEM,
|
|
.name = "regs",
|
|
},
|
|
{
|
|
.flags = IORESOURCE_MEM,
|
|
.name = "smi",
|
|
},
|
|
{
|
|
.flags = IORESOURCE_MEM,
|
|
.name = "ebi",
|
|
},
|
|
{
|
|
.start = INT_GRAPHICS,
|
|
.end = INT_GRAPHICS,
|
|
.flags = IORESOURCE_IRQ,
|
|
.name = "gfx",
|
|
},
|
|
};
|
|
|
|
static struct platform_device hw3d_device = {
|
|
.name = "msm_hw3d",
|
|
.id = 0,
|
|
.num_resources = ARRAY_SIZE(resources_hw3d),
|
|
.resource = resources_hw3d,
|
|
};
|
|
|
|
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 && setting->pmem_gpu1_size) {
|
|
struct resource *res;
|
|
|
|
res = platform_get_resource_byname(&hw3d_device, IORESOURCE_MEM,
|
|
"smi");
|
|
res->start = setting->pmem_gpu0_start;
|
|
res->end = res->start + setting->pmem_gpu0_size - 1;
|
|
|
|
res = platform_get_resource_byname(&hw3d_device, IORESOURCE_MEM,
|
|
"ebi");
|
|
res->start = setting->pmem_gpu1_start;
|
|
res->end = res->start + setting->pmem_gpu1_size - 1;
|
|
platform_device_register(&hw3d_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;
|
|
else if (!strcmp(s, "power_test"))
|
|
mfg_mode = 4;
|
|
else if (!strcmp(s, "offmode_charging"))
|
|
mfg_mode = 5;
|
|
|
|
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)
|
|
{
|
|
#ifdef CONFIG_USB_ANDROID_RNDIS
|
|
int i;
|
|
char *src;
|
|
#endif
|
|
char *str;
|
|
|
|
/* use default serial number when mode is factory2 */
|
|
if (mfg_mode == 1 || !strlen(serialno))
|
|
str = df_serialno;
|
|
else
|
|
str = serialno;
|
|
|
|
#ifdef CONFIG_USB_ANDROID_RNDIS
|
|
/* create a fake MAC address from our serial number.
|
|
* first byte is 0x02 to signify locally administered.
|
|
*/
|
|
rndis_pdata.ethaddr[0] = 0x02;
|
|
src = str;
|
|
for (i = 0; *src; i++) {
|
|
/* XOR the USB serial across the remaining bytes */
|
|
rndis_pdata.ethaddr[i % (ETH_ALEN - 1) + 1] ^= *src++;
|
|
}
|
|
#endif
|
|
android_usb_pdata.serial_number = str;
|
|
return 1;
|
|
}
|
|
|
|
__setup("androidboot.serialno=", board_serialno_setup);
|