| /* 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); |