/* linux/arch/arm/mach-msm/devices.c * * Copyright (C) 2008 Google, Inc. * Copyright (C) 2007-2009 HTC Corporation. * Author: Thomas Tsai * * 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 #include #include #include #include #include "gpio_chip.h" #include "devices.h" #include #include #include #include #include #include #include #include #include #include #include #include #include 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; 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);