M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
#Android makefile to build lk bootloader as a part of Android Build
# Set flags if we need to include security libs
ifeq ($(TARGET_BOOTIMG_SIGNED),true)
SIGNED_KERNEL := SIGNED_KERNEL=1
else
SIGNED_KERNEL := SIGNED_KERNEL=0
endif
ifeq ($(call is-board-platform,msm8660),true)
BOOTLOADER_PLATFORM := msm8660_surf
else
BOOTLOADER_PLATFORM := $(TARGET_BOARD_PLATFORM)
endif
# NAND variant output
TARGET_NAND_BOOTLOADER := $(PRODUCT_OUT)/appsboot.mbn
NAND_BOOTLOADER_OUT := $(TARGET_OUT_INTERMEDIATES)/NAND_BOOTLOADER_OBJ
# Remove bootloader binary to trigger recompile when source changes
appsbootldr_clean:
$(hide) rm -f $(TARGET_NAND_BOOTLOADER)
$(NAND_BOOTLOADER_OUT):
mkdir -p $(NAND_BOOTLOADER_OUT)
# eMMC variant output
TARGET_EMMC_BOOTLOADER := $(PRODUCT_OUT)/emmc_appsboot.mbn
EMMC_BOOTLOADER_OUT := $(TARGET_OUT_INTERMEDIATES)/EMMC_BOOTLOADER_OBJ
emmc_appsbootldr_clean:
$(hide) rm -f $(TARGET_EMMC_BOOTLOADER)
$(EMMC_BOOTLOADER_OUT):
mkdir -p $(EMMC_BOOTLOADER_OUT)
# Top level for NAND variant targets
$(TARGET_NAND_BOOTLOADER): appsbootldr_clean | $(NAND_BOOTLOADER_OUT)
$(MAKE) -C bootable/bootloader/lk BOOTLOADER_OUT=../../../$(NAND_BOOTLOADER_OUT) $(BOOTLOADER_PLATFORM) $(SIGNED_KERNEL)
# Top level for eMMC variant targets
$(TARGET_EMMC_BOOTLOADER): emmc_appsbootldr_clean | $(EMMC_BOOTLOADER_OUT)
$(MAKE) -C bootable/bootloader/lk BOOTLOADER_OUT=../../../$(EMMC_BOOTLOADER_OUT) $(BOOTLOADER_PLATFORM) EMMC_BOOT=1 $(SIGNED_KERNEL)
# Keep build NAND & eMMC as default for targets still using TARGET_BOOTLOADER
TARGET_BOOTLOADER := $(PRODUCT_OUT)/EMMCBOOT.MBN
$(TARGET_BOOTLOADER): $(NAND_BOOTLOADER_OUT) $(EMMC_BOOTLOADER_OUT) | $(TARGET_NAND_BOOTLOADER) $(TARGET_EMMC_BOOTLOADER)
#
# Build nandwrite as a part of Android Build for NAND configurations
#
TARGET_NANDWRITE := $(PRODUCT_OUT)/obj/nandwrite/build-$(BOOTLOADER_PLATFORM)_nandwrite/lk
NANDWRITE_OUT := $(TARGET_OUT_INTERMEDIATES)/nandwrite
nandwrite_clean:
$(hide) rm -f $(TARGET_NANDWRITE)
$(hide) rm -rf $(NANDWRITE_OUT)
$(NANDWRITE_OUT):
mkdir -p $(NANDWRITE_OUT)
$(TARGET_NANDWRITE): nandwrite_clean | $(NANDWRITE_OUT)
@echo $(BOOTLOADER_PLATFORM)_nandwrite
$(MAKE) -C bootable/bootloader/lk BOOTLOADER_OUT=../../../$(NANDWRITE_OUT) $(BOOTLOADER_PLATFORM)_nandwrite BUILD_NANDWRITE=1
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2008-2010 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
File diff suppressed because it is too large Load Diff
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr boot_img_hdr;
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];
unsigned kernel_size; /* size in bytes */
unsigned kernel_addr; /* physical load addr */
unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */
unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */
unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned dt_size; /* device_tree in bytes */
unsigned unused; /* future expansion: should be 0 */
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
unsigned char cmdline[BOOT_ARGS_SIZE];
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
** | device tree | p pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
** p = (dt_size + page_size - 1) / page_size
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
void *ramdisk, unsigned ramdisk_size,
void *second, unsigned second_size,
unsigned page_size,
unsigned *bootimg_size);
void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
#endif
@@ -0,0 +1,45 @@
/*
* * Copyright (c) 2011, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEVINFO_H_
#define _DEVINFO_H_
typedef struct device_info device_info;
#define DEVICE_MAGIC "ANDROID-BOOT!"
#define DEVICE_MAGIC_SIZE 13
struct device_info
{
unsigned char magic[DEVICE_MAGIC_SIZE];
bool is_unlocked;
bool is_tampered;
};
#endif
+408
View File
@@ -0,0 +1,408 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <debug.h>
#include <string.h>
#include <stdlib.h>
#include <platform.h>
#include <kernel/thread.h>
#include <kernel/event.h>
#include <dev/udc.h>
#include "fastboot.h"
#define MAX_USBFS_BULK_SIZE (32 * 1024)
void boot_linux(void *bootimg, unsigned sz);
/* todo: give lk strtoul and nuke this */
static unsigned hex2unsigned(const char *x)
{
unsigned n = 0;
while(*x) {
switch(*x) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n = (n << 4) | (*x - '0');
break;
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
n = (n << 4) | (*x - 'a' + 10);
break;
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
n = (n << 4) | (*x - 'A' + 10);
break;
default:
return n;
}
x++;
}
return n;
}
struct fastboot_cmd {
struct fastboot_cmd *next;
const char *prefix;
unsigned prefix_len;
void (*handle)(const char *arg, void *data, unsigned sz);
};
struct fastboot_var {
struct fastboot_var *next;
const char *name;
const char *value;
};
static struct fastboot_cmd *cmdlist;
void fastboot_register(const char *prefix,
void (*handle)(const char *arg, void *data, unsigned sz))
{
struct fastboot_cmd *cmd;
cmd = malloc(sizeof(*cmd));
if (cmd) {
cmd->prefix = prefix;
cmd->prefix_len = strlen(prefix);
cmd->handle = handle;
cmd->next = cmdlist;
cmdlist = cmd;
}
}
static struct fastboot_var *varlist;
void fastboot_publish(const char *name, const char *value)
{
struct fastboot_var *var;
var = malloc(sizeof(*var));
if (var) {
var->name = name;
var->value = value;
var->next = varlist;
varlist = var;
}
}
static event_t usb_online;
static event_t txn_done;
static struct udc_endpoint *in, *out;
static struct udc_request *req;
int txn_status;
static void *download_base;
static unsigned download_max;
static unsigned download_size;
#define STATE_OFFLINE 0
#define STATE_COMMAND 1
#define STATE_COMPLETE 2
#define STATE_ERROR 3
static unsigned fastboot_state = STATE_OFFLINE;
static void req_complete(struct udc_request *req, unsigned actual, int status)
{
txn_status = status;
req->length = actual;
event_signal(&txn_done, 0);
}
static int usb_read(void *_buf, unsigned len)
{
int r;
unsigned xfer;
unsigned char *buf = _buf;
int count = 0;
if (fastboot_state == STATE_ERROR)
goto oops;
while (len > 0) {
xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
req->buf = PA((addr_t)buf);
req->length = xfer;
req->complete = req_complete;
r = udc_request_queue(out, req);
if (r < 0) {
dprintf(INFO, "usb_read() queue failed\n");
goto oops;
}
event_wait(&txn_done);
if (txn_status < 0) {
dprintf(INFO, "usb_read() transaction failed\n");
goto oops;
}
count += req->length;
buf += req->length;
len -= req->length;
/* short transfer? */
if (req->length != xfer) break;
}
/*
* Force reload of buffer from memory
* since transaction is complete now.
*/
arch_invalidate_cache_range(_buf, count);
return count;
oops:
fastboot_state = STATE_ERROR;
return -1;
}
static int usb_write(void *buf, unsigned len)
{
int r;
if (fastboot_state == STATE_ERROR)
goto oops;
req->buf = PA((addr_t)buf);
req->length = len;
req->complete = req_complete;
r = udc_request_queue(in, req);
if (r < 0) {
dprintf(INFO, "usb_write() queue failed\n");
goto oops;
}
event_wait(&txn_done);
if (txn_status < 0) {
dprintf(INFO, "usb_write() transaction failed\n");
goto oops;
}
return req->length;
oops:
fastboot_state = STATE_ERROR;
return -1;
}
void fastboot_ack(const char *code, const char *reason)
{
STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
if (fastboot_state != STATE_COMMAND)
return;
if (reason == 0)
reason = "";
snprintf(response, MAX_RSP_SIZE, "%s%s", code, reason);
fastboot_state = STATE_COMPLETE;
usb_write(response, strlen(response));
}
void fastboot_info(const char *reason)
{
STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
if (fastboot_state != STATE_COMMAND)
return;
if (reason == 0)
return;
snprintf(response, MAX_RSP_SIZE, "INFO%s", reason);
usb_write(response, strlen(response));
}
void fastboot_fail(const char *reason)
{
fastboot_ack("FAIL", reason);
}
void fastboot_okay(const char *info)
{
fastboot_ack("OKAY", info);
}
static void cmd_getvar(const char *arg, void *data, unsigned sz)
{
struct fastboot_var *var;
for (var = varlist; var; var = var->next) {
if (!strcmp(var->name, arg)) {
fastboot_okay(var->value);
return;
}
}
fastboot_okay("");
}
static void cmd_download(const char *arg, void *data, unsigned sz)
{
STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
unsigned len = hex2unsigned(arg);
int r;
download_size = 0;
if (len > download_max) {
fastboot_fail("data too large");
return;
}
snprintf(response, MAX_RSP_SIZE, "DATA%08x", len);
if (usb_write(response, strlen(response)) < 0)
return;
r = usb_read(download_base, len);
if ((r < 0) || ((unsigned) r != len)) {
fastboot_state = STATE_ERROR;
return;
}
download_size = len;
fastboot_okay("");
}
static void fastboot_command_loop(void)
{
struct fastboot_cmd *cmd;
int r;
dprintf(INFO,"fastboot: processing commands\n");
uint8_t *buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(4096, CACHE_LINE));
if (!buffer)
{
dprintf(CRITICAL, "Could not allocate memory for fastboot buffer\n.");
ASSERT(0);
}
again:
while (fastboot_state != STATE_ERROR) {
r = usb_read(buffer, MAX_RSP_SIZE);
if (r < 0) break;
buffer[r] = 0;
dprintf(INFO,"fastboot: %s\n", buffer);
for (cmd = cmdlist; cmd; cmd = cmd->next) {
if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
continue;
fastboot_state = STATE_COMMAND;
cmd->handle((const char*) buffer + cmd->prefix_len,
(void*) download_base, download_size);
if (fastboot_state == STATE_COMMAND)
fastboot_fail("unknown reason");
goto again;
}
fastboot_fail("unknown command");
}
fastboot_state = STATE_OFFLINE;
dprintf(INFO,"fastboot: oops!\n");
free(buffer);
}
static int fastboot_handler(void *arg)
{
for (;;) {
event_wait(&usb_online);
fastboot_command_loop();
}
return 0;
}
static void fastboot_notify(struct udc_gadget *gadget, unsigned event)
{
if (event == UDC_EVENT_ONLINE) {
event_signal(&usb_online, 0);
}
}
static struct udc_endpoint *fastboot_endpoints[2];
static struct udc_gadget fastboot_gadget = {
.notify = fastboot_notify,
.ifc_class = 0xff,
.ifc_subclass = 0x42,
.ifc_protocol = 0x03,
.ifc_endpoints = 2,
.ifc_string = "fastboot",
.ept = fastboot_endpoints,
};
int fastboot_init(void *base, unsigned size)
{
thread_t *thr;
dprintf(INFO, "fastboot_init()\n");
download_base = base;
download_max = size;
event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);
event_init(&txn_done, 0, EVENT_FLAG_AUTOUNSIGNAL);
in = udc_endpoint_alloc(UDC_TYPE_BULK_IN, 512);
if (!in)
goto fail_alloc_in;
out = udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
if (!out)
goto fail_alloc_out;
fastboot_endpoints[0] = in;
fastboot_endpoints[1] = out;
req = udc_request_alloc();
if (!req)
goto fail_alloc_req;
if (udc_register_gadget(&fastboot_gadget))
goto fail_udc_register;
fastboot_register("getvar:", cmd_getvar);
fastboot_register("download:", cmd_download);
fastboot_publish("version", "0.5");
thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, 4096);
if (!thr)
{
goto fail_alloc_in;
}
thread_resume(thr);
return 0;
fail_udc_register:
udc_request_free(req);
fail_alloc_req:
udc_endpoint_free(out);
fail_alloc_out:
udc_endpoint_free(in);
fail_alloc_in:
return -1;
}
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __APP_FASTBOOT_H
#define __APP_FASTBOOT_H
#define MAX_RSP_SIZE 64
#define MAX_GET_VAR_NAME_SIZE 256
int fastboot_init(void *xfer_buffer, unsigned max);
/* register a command handler
* - command handlers will be called if their prefix matches
* - they are expected to call fastboot_okay() or fastboot_fail()
* to indicate success/failure before returning
*/
void fastboot_register(const char *prefix,
void (*handle)(const char *arg, void *data, unsigned size));
/* publish a variable readable by the built-in getvar command */
void fastboot_publish(const char *name, const char *value);
/* only callable from within a command handler */
void fastboot_okay(const char *result);
void fastboot_fail(const char *reason);
void fastboot_info(const char *reason);
#endif
+659
View File
@@ -0,0 +1,659 @@
/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <debug.h>
#include <arch/arm.h>
#include <dev/udc.h>
#include <string.h>
#include <kernel/thread.h>
#include <arch/ops.h>
#include <dev/flash.h>
#include <lib/ptable.h>
#include <dev/keys.h>
#include <platform.h>
#include <target.h>
#include <partition_parser.h>
#include <mmc.h>
#include "recovery.h"
#include "bootimg.h"
#include "smem.h"
#define BOOT_FLAGS 1
#define UPDATE_STATUS 2
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
static const int MISC_PAGES = 3; // number of pages to save
static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page
static char buf[4096];
unsigned boot_into_recovery = 0;
extern uint32_t get_page_size();
extern void reset_device_info();
extern void set_device_root();
int get_recovery_message(struct recovery_message *out)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
unsigned pagesize = flash_page_size();
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "misc");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No misc partition found\n");
return -1;
}
offset += (pagesize * MISC_COMMAND_PAGE);
if (flash_read(ptn, offset, (void *) buf, pagesize)) {
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
return -1;
}
memcpy(out, buf, sizeof(*out));
return 0;
}
int set_recovery_message(const struct recovery_message *in)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
unsigned pagesize = flash_page_size();
unsigned n = 0;
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "misc");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No misc partition found\n");
return -1;
}
n = pagesize * (MISC_COMMAND_PAGE + 1);
if (flash_read(ptn, offset, (void *) SCRATCH_ADDR, n)) {
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
return -1;
}
offset += (pagesize * MISC_COMMAND_PAGE);
offset += SCRATCH_ADDR;
memcpy((void *) offset, in, sizeof(*in));
if (flash_write(ptn, 0, (void *)SCRATCH_ADDR, n)) {
dprintf(CRITICAL, "ERROR: flash write fail!\n");
return -1;
}
return 0;
}
int read_update_header_for_bootloader(struct update_header *header)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
unsigned pagesize = flash_page_size();
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "cache");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No cache partition found\n");
return -1;
}
if (flash_read(ptn, offset, buf, pagesize)) {
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
return -1;
}
memcpy(header, buf, sizeof(*header));
if (strncmp((char *) header->MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE))
{
return -1;
}
return 0;
}
int update_firmware_image (struct update_header *header, char *name)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
unsigned pagesize = flash_page_size();
unsigned pagemask = pagesize -1;
unsigned n = 0;
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "cache");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No cache partition found\n");
return -1;
}
offset += header->image_offset;
n = (header->image_length + pagemask) & (~pagemask);
if (flash_read(ptn, offset, (void *) SCRATCH_ADDR, n)) {
dprintf(CRITICAL, "ERROR: Cannot read radio image\n");
return -1;
}
ptn = ptable_find(ptable, name);
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
return -1;
}
if (flash_write(ptn, 0, (void *) SCRATCH_ADDR, n)) {
dprintf(CRITICAL, "ERROR: flash write fail!\n");
return -1;
}
dprintf(INFO, "Partition writen successfully!");
return 0;
}
static int set_ssd_radio_update (char *name)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned int ssd_cookie[2] = {0x53534443, 0x4F4F4B49};
unsigned pagesize = flash_page_size();
unsigned pagemask = pagesize -1;
unsigned n = 0;
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
n = (sizeof(ssd_cookie) + pagemask) & (~pagemask);
ptn = ptable_find(ptable, name);
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
return -1;
}
if (flash_write(ptn, 0, ssd_cookie, n)) {
dprintf(CRITICAL, "ERROR: flash write fail!\n");
return -1;
}
dprintf(INFO, "FOTA partition written successfully!");
return 0;
}
int get_boot_info_apps (char type, unsigned int *status)
{
boot_info_for_apps apps_boot_info;
int ret = 0;
ret = smem_read_alloc_entry(SMEM_BOOT_INFO_FOR_APPS,
&apps_boot_info, sizeof(apps_boot_info));
if (ret)
{
dprintf(CRITICAL, "ERROR: unable to read shared memory for apps boot info %d\n",ret);
return ret;
}
dprintf(INFO,"boot flag %x update status %x\n",apps_boot_info.boot_flags,
apps_boot_info.status.update_status);
if(type == BOOT_FLAGS)
*status = apps_boot_info.boot_flags;
else if(type == UPDATE_STATUS)
*status = apps_boot_info.status.update_status;
return ret;
}
/* Bootloader / Recovery Flow
*
* On every boot, the bootloader will read the recovery_message
* from flash and check the command field. The bootloader should
* deal with the command field not having a 0 terminator correctly
* (so as to not crash if the block is invalid or corrupt).
*
* The bootloader will have to publish the partition that contains
* the recovery_message to the linux kernel so it can update it.
*
* if command == "boot-recovery" -> boot recovery.img
* else if command == "update-radio" -> update radio image (below)
* else -> boot boot.img (normal boot)
*
* Radio Update Flow
* 1. the bootloader will attempt to load and validate the header
* 2. if the header is invalid, status="invalid-update", goto #8
* 3. display the busy image on-screen
* 4. if the update image is invalid, status="invalid-radio-image", goto #8
* 5. attempt to update the firmware (depending on the command)
* 6. if successful, status="okay", goto #8
* 7. if failed, and the old image can still boot, status="failed-update"
* 8. write the recovery_message, leaving the recovery field
* unchanged, updating status, and setting command to
* "boot-recovery"
* 9. reboot
*
* The bootloader will not modify or erase the cache partition.
* It is recovery's responsibility to clean up the mess afterwards.
*/
int recovery_init (void)
{
struct recovery_message msg;
char partition_name[32];
unsigned valid_command = 0;
int update_status = 0;
// get recovery message
if (get_recovery_message(&msg))
return -1;
msg.command[sizeof(msg.command)-1] = '\0'; //Ensure termination
if (msg.command[0] != 0 && msg.command[0] != 255) {
dprintf(INFO,"Recovery command: %d %s\n",
sizeof(msg.command), msg.command);
}
if (!strcmp("boot-recovery",msg.command))
{
if(!strcmp("RADIO",msg.status))
{
/* We're now here due to radio update, so check for update status */
int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status);
if(!ret && (update_status & 0x01))
{
dprintf(INFO,"radio update success\n");
strlcpy(msg.status, "OKAY", sizeof(msg.status));
}
else
{
dprintf(INFO,"radio update failed\n");
strlcpy(msg.status, "failed-update", sizeof(msg.status));
}
strlcpy(msg.command, "", sizeof(msg.command)); // clearing recovery command
set_recovery_message(&msg); // send recovery message
boot_into_recovery = 1; // Boot in recovery mode
return 0;
}
valid_command = 1;
strlcpy(msg.command, "", sizeof(msg.command)); // to safe against multiple reboot into recovery
strlcpy(msg.status, "OKAY", sizeof(msg.status));
set_recovery_message(&msg); // send recovery message
boot_into_recovery = 1; // Boot in recovery mode
return 0;
}
if (!strcmp("update-radio",msg.command)) {
dprintf(INFO,"start radio update\n");
valid_command = 1;
strlcpy(partition_name, "FOTA", sizeof(partition_name));
}
//Todo: Add support for bootloader update too.
if(!valid_command) {
//We need not to do anything
return 0; // Boot in normal mode
}
#ifdef OLD_FOTA_UPGRADE
if (read_update_header_for_bootloader(&header)) {
strlcpy(msg.status, "invalid-update", sizeof(msg.status));
goto SEND_RECOVERY_MSG;
}
if (update_firmware_image (&header, partition_name)) {
strlcpy(msg.status, "failed-update", sizeof(msg.status));
goto SEND_RECOVERY_MSG;
}
#else
if (set_ssd_radio_update(partition_name)) {
/* If writing to FOTA partition fails */
strlcpy(msg.command, "", sizeof(msg.command));
strlcpy(msg.status, "failed-update", sizeof(msg.status));
goto SEND_RECOVERY_MSG;
}
else {
/* Setting this to check the radio update status */
strlcpy(msg.command, "boot-recovery", sizeof(msg.command));
strlcpy(msg.status, "RADIO", sizeof(msg.status));
goto SEND_RECOVERY_MSG;
}
#endif
strlcpy(msg.status, "OKAY", sizeof(msg.status));
SEND_RECOVERY_MSG:
set_recovery_message(&msg); // send recovery message
boot_into_recovery = 1; // Boot in recovery mode
reboot_device(0);
return 0;
}
static int emmc_set_recovery_msg(struct recovery_message *out)
{
char *ptn_name = "misc";
unsigned long long ptn = 0;
unsigned int size = ROUND_TO_PAGE(sizeof(*out),511);
unsigned char data[size];
int index = INVALID_PTN;
index = partition_get_index((unsigned char *) ptn_name);
ptn = partition_get_offset(index);
if(ptn == 0) {
dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
return -1;
}
memcpy(data, out, sizeof(*out));
if (mmc_write(ptn , size, (unsigned int*)data)) {
dprintf(CRITICAL,"mmc write failure %s %d\n",ptn_name, sizeof(*out));
return -1;
}
return 0;
}
static int emmc_get_recovery_msg(struct recovery_message *in)
{
char *ptn_name = "misc";
unsigned long long ptn = 0;
unsigned int size = ROUND_TO_PAGE(sizeof(*in),511);
unsigned char data[size];
int index = INVALID_PTN;
index = partition_get_index((unsigned char *) ptn_name);
ptn = partition_get_offset(index);
if(ptn == 0) {
dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
return -1;
}
if (mmc_read(ptn , (unsigned int*)data, size)) {
dprintf(CRITICAL,"mmc read failure %s %d\n",ptn_name, size);
return -1;
}
memcpy(in, data, sizeof(*in));
return 0;
}
int _emmc_recovery_init(void)
{
int update_status = 0;
struct recovery_message msg;
// get recovery message
if(emmc_get_recovery_msg(&msg))
return -1;
msg.command[sizeof(msg.command)-1] = '\0'; //Ensure termination
if (msg.command[0] != 0 && msg.command[0] != 255) {
dprintf(INFO,"Recovery command: %d %s\n",
sizeof(msg.command), msg.command);
}
if (!strncmp(msg.command, "boot-recovery", strlen("boot-recovery"))) {
boot_into_recovery = 1;
}
if (!strcmp("update-radio",msg.command))
{
/* We're now here due to radio update, so check for update status */
int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status);
if(!ret && (update_status & 0x01))
{
dprintf(INFO,"radio update success\n");
strlcpy(msg.status, "OKAY", sizeof(msg.status));
}
else
{
dprintf(INFO,"radio update failed\n");
strlcpy(msg.status, "failed-update", sizeof(msg.status));
}
boot_into_recovery = 1; // Boot in recovery mode
}
if (!strcmp("reset-device-info",msg.command))
{
reset_device_info();
}
if (!strcmp("root-detect",msg.command))
{
set_device_root();
}
else
return 0; // do nothing
strlcpy(msg.command, "", sizeof(msg.command)); // clearing recovery command
emmc_set_recovery_msg(&msg); // send recovery message
return 0;
}
static int read_misc(unsigned page_offset, void *buf, unsigned size)
{
const char *ptn_name = "misc";
uint32_t pagesize = get_page_size();
unsigned offset;
if (size == 0 || buf == NULL)
return -1;
offset = page_offset * pagesize;
if (target_is_emmc_boot())
{
int index;
unsigned long long ptn;
unsigned long long ptn_size;
index = partition_get_index(ptn_name);
if (index == INVALID_PTN)
{
dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
return -1;
}
ptn = partition_get_offset(index);
ptn_size = partition_get_size(index);
if (ptn_size < offset + size)
{
dprintf(CRITICAL, "Read request out of '%s' boundaries\n",
ptn_name);
return -1;
}
if (mmc_read(ptn + offset, (unsigned int *)buf, size))
{
dprintf(CRITICAL, "Reading MMC failed\n");
return -1;
}
}
else
{
dprintf(CRITICAL, "Misc partition not supported for NAND targets.\n");
return -1;
}
return 0;
}
int write_misc(unsigned page_offset, void *buf, unsigned size)
{
const char *ptn_name = "misc";
void *scratch_addr = target_get_scratch_address();
unsigned offset;
unsigned aligned_size;
if (size == 0 || buf == NULL || scratch_addr == NULL)
return -1;
if (target_is_emmc_boot())
{
int index;
unsigned long long ptn;
unsigned long long ptn_size;
index = partition_get_index(ptn_name);
if (index == INVALID_PTN)
{
dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
return -1;
}
ptn = partition_get_offset(index);
ptn_size = partition_get_size(index);
offset = page_offset * BLOCK_SIZE;
aligned_size = ROUND_TO_PAGE(size, (unsigned)BLOCK_SIZE - 1);
if (ptn_size < offset + aligned_size)
{
dprintf(CRITICAL, "Write request out of '%s' boundaries\n",
ptn_name);
return -1;
}
if (scratch_addr != buf)
memcpy(scratch_addr, buf, size);
if (mmc_write(ptn + offset, aligned_size, (unsigned int *)scratch_addr))
{
dprintf(CRITICAL, "Writing MMC failed\n");
return -1;
}
}
else
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned pagesize = flash_page_size();
ptable = flash_get_ptable();
if (ptable == NULL)
{
dprintf(CRITICAL, "Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, ptn_name);
if (ptn == NULL)
{
dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
return -1;
}
offset = page_offset * pagesize;
aligned_size = ROUND_TO_PAGE(size, pagesize - 1);
if (ptn->length < offset + aligned_size)
{
dprintf(CRITICAL, "Write request out of '%s' boundaries\n",
ptn_name);
return -1;
}
if (scratch_addr != buf)
memcpy(scratch_addr, buf, size);
if (flash_write(ptn, offset, scratch_addr, aligned_size)) {
dprintf(CRITICAL, "Writing flash failed\n");
return -1;
}
}
return 0;
}
int get_ffbm(char *ffbm, unsigned size)
{
const char *ffbm_cmd = "ffbm-";
uint32_t page_size = get_page_size();
char *ffbm_page_buffer = NULL;
int retval = 0;
if (size < FFBM_MODE_BUF_SIZE || size >= page_size)
{
dprintf(CRITICAL, "Invalid size argument passed to get_ffbm\n");
retval = -1;
goto cleanup;
}
ffbm_page_buffer = (char*)malloc(page_size);
if (!ffbm_page_buffer)
{
dprintf(CRITICAL, "Failed to alloc buffer for ffbm cookie\n");
retval = -1;
goto cleanup;
}
if (read_misc(0, ffbm_page_buffer, page_size))
{
dprintf(CRITICAL, "Error reading MISC partition\n");
retval = -1;
goto cleanup;
}
ffbm_page_buffer[size] = '\0';
if (strncmp(ffbm_cmd, ffbm_page_buffer, strlen(ffbm_cmd)))
{
retval = 0;
goto cleanup;
}
else
{
if (strlcpy(ffbm, ffbm_page_buffer, size) <
FFBM_MODE_BUF_SIZE -1)
{
dprintf(CRITICAL, "Invalid string in misc partition\n");
retval = -1;
}
else
retval = 1;
}
cleanup:
if(ffbm_page_buffer)
free(ffbm_page_buffer);
return retval;
}
@@ -0,0 +1,86 @@
/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BOOTLOADER_RECOVERY_H
#define _BOOTLOADER_RECOVERY_H
#define UPDATE_MAGIC "MSM-RADIO-UPDATE"
#define UPDATE_MAGIC_SIZE 16
#define UPDATE_VERSION 0x00010000
#define FFBM_MODE_BUF_SIZE 8
/* Recovery Message */
struct recovery_message {
char command[32];
char status[32];
char recovery[1024];
};
struct update_header {
unsigned char MAGIC[UPDATE_MAGIC_SIZE];
unsigned version;
unsigned size;
unsigned image_offset;
unsigned image_length;
unsigned bitmap_width;
unsigned bitmap_height;
unsigned bitmap_bpp;
unsigned busy_bitmap_offset;
unsigned busy_bitmap_length;
unsigned fail_bitmap_offset;
unsigned fail_bitmap_length;
};
int write_misc(unsigned page_offset, void *buf, unsigned size);
int get_recovery_message(struct recovery_message *out);
int set_recovery_message(const struct recovery_message *in);
int read_update_header_for_bootloader(struct update_header *header);
int update_firmware_image (struct update_header *header, char *name);
int recovery_init (void);
/* This function will look for the ffbm cookie in the misc partition.
* Upon finding a valid cookie it will return 1 and place the cookie
* into ffbm.If it does not find a valid cookie it will return 0.If
* an error is hit it will return -1.If either of these return values
* is seen the data in ffbm should not be used and should be considered
* invalid.
*/
int get_ffbm(char *ffbm, unsigned size);
extern unsigned boot_into_recovery;
#endif
@@ -0,0 +1,9 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
INCLUDES += -I$(LK_TOP_DIR)/platform/msm_shared/include
OBJS += \
$(LOCAL_DIR)/aboot.o \
$(LOCAL_DIR)/fastboot.o \
$(LOCAL_DIR)/recovery.o
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
typedef struct sparse_header {
uint32_t magic; /* 0xed26ff3a */
uint16_t major_version; /* (0x1) - reject images with higher major versions */
uint16_t minor_version; /* (0x0) - allow images with higer minor versions */
uint16_t file_hdr_sz; /* 28 bytes for first revision of the file format */
uint16_t chunk_hdr_sz; /* 12 bytes for first revision of the file format */
uint32_t blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */
uint32_t total_blks; /* total blocks in the non-sparse output image */
uint32_t total_chunks; /* total chunks in the sparse input image */
uint32_t image_checksum; /* CRC32 checksum of the original data, counting "don't care" */
/* as 0. Standard 802.3 polynomial, use a Public Domain */
/* table implementation */
} sparse_header_t;
#define SPARSE_HEADER_MAGIC 0xed26ff3a
#define CHUNK_TYPE_RAW 0xCAC1
#define CHUNK_TYPE_FILL 0xCAC2
#define CHUNK_TYPE_DONT_CARE 0xCAC3
#define CHUNK_TYPE_CRC 0xCAC4
typedef struct chunk_header {
uint16_t chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
uint16_t reserved1;
uint32_t chunk_sz; /* in blocks in output image */
uint32_t total_sz; /* in bytes of chunk input file including chunk header and data */
} chunk_header_t;
/* Following a Raw or Fill chunk is data. For a Raw chunk, it's the data in chunk_sz * blk_sz.
* For a Fill chunk, it's 4 bytes of the fill data.
*/
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2009 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <app.h>
#include <kernel/thread.h>
extern const struct app_descriptor __apps_start;
extern const struct app_descriptor __apps_end;
static void start_app(const struct app_descriptor *app);
/* one time setup */
void apps_init(void)
{
const struct app_descriptor *app;
/* call all the init routines */
for (app = &__apps_start; app != &__apps_end; app++) {
if (app->init)
app->init(app);
}
/* start any that want to start on boot */
for (app = &__apps_start; app != &__apps_end; app++) {
if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) {
start_app(app);
}
}
}
static int app_thread_entry(void *arg)
{
const struct app_descriptor *app = (const struct app_descriptor *)arg;
app->entry(app, NULL);
return 0;
}
static void start_app(const struct app_descriptor *app)
{
thread_t *thr;
printf("starting app %s\n", app->name);
thr = thread_create(app->name, &app_thread_entry, (void *)app, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
if(!thr)
{
return;
}
thread_resume(thr);
}
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of The Linux Foundation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <debug.h>
#include <string.h>
#include <app.h>
#include <platform.h>
#include <kernel/thread.h>
#include <err.h>
#if defined(WITH_LIB_CONSOLE) && defined(DEBUG_CLOCK)
#include <lib/console.h>
#include <clock.h>
static void print_clock_list()
{
unsigned i;
struct clk_lookup *cl;
unsigned num;
struct clk_list *clock_list = clk_get_list();
if(!clock_list)
return;
cl = clock_list->clist;
num = clock_list->num;
if(!cl || !num)
return;
printf("Clock list:\n");
for(i=0; i < num; i++, cl++)
{
printf("%s\n", cl->con_id);
}
}
static int clock_measure(const char *id)
{
int ret = NO_ERROR;
struct clk *cp, *mcp;
unsigned long rate;
/* Get clk */
cp = clk_get(id);
if(!cp)
{
ret = ERR_NOT_VALID;
goto measure_error;
}
/* Get measure clk */
mcp = clk_get("measure");
if(!mcp)
{
ret = ERR_NOT_VALID;
goto measure_error;
}
/* Set parent clk */
clk_set_parent(mcp, cp);
rate = clk_get_rate(mcp);
printf("Clock %s is running at: %lu Hz.\n", id, rate);
measure_error:
return ret;
}
static int clock_tests(int argc, cmd_args *argv)
{
if (argc < 2) {
printf("not enough arguments:\n");
printf("%s <clock-name>\n", argv[0].str);
printf("%s ?\n", argv[0].str);
goto out;
}
if(argv[1].str[0] == '?')
print_clock_list();
else
clock_measure(argv[1].str);
out:
return 0;
}
STATIC_COMMAND_START
{ "test_clock", "Test Clock", &clock_tests },
STATIC_COMMAND_END(clocktests);
#endif
APP_START(clocktests)
APP_END
@@ -0,0 +1,6 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
INCLUDES += -I$(LK_TOP_DIR)/platform/msm_shared/include
OBJS += \
$(LOCAL_DIR)/clock_tests.o
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
* Copyright (c) 2009, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr boot_img_hdr;
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];
unsigned kernel_size; /* size in bytes */
unsigned kernel_addr; /* physical load addr */
unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */
unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */
unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned unused[2]; /* future expansion: should be 0 */
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
unsigned char cmdline[BOOT_ARGS_SIZE];
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
void *ramdisk, unsigned ramdisk_size,
void *second, unsigned second_size,
unsigned page_size,
unsigned *bootimg_size);
void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
#endif
@@ -0,0 +1,220 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
* Copyright (c) 2009, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <app.h>
#include <debug.h>
#include <lib/ptable.h>
#include <malloc.h>
#include <dev/flash.h>
#include <string.h>
#include <jtag.h>
#include <kernel/thread.h>
#include <smem.h>
#include <platform.h>
#include "bootimg.h"
#define FLASH_PAGE_SIZE 2048
#define FLASH_PAGE_BITS 11
unsigned page_size = 0;
unsigned page_mask = 0;
static unsigned load_addr = 0xffffffff;
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
void acpu_clock_init(void);
int startswith(const char *str, const char *prefix)
{
while(*prefix){
if (*prefix++ != *str++) return 0;
}
return 1;
}
/* XXX */
void verify_flash(struct ptentry *p, void *addr, unsigned len, int extra)
{
uint32_t offset = 0;
void *buf = malloc(FLASH_PAGE_SIZE + extra);
int verify_extra = extra;
if(verify_extra > 4)
verify_extra = 16;
while(len > 0) {
flash_read_ext(p, extra, offset, buf, FLASH_PAGE_SIZE);
if(memcmp(addr, buf, FLASH_PAGE_SIZE + verify_extra)) {
dprintf(CRITICAL, "verify failed at 0x%08x\n", offset);
jtag_fail("verify failed");
return;
}
offset += FLASH_PAGE_SIZE;
addr += FLASH_PAGE_SIZE;
len -= FLASH_PAGE_SIZE;
if(extra) {
addr += extra;
len -= extra;
}
}
dprintf(INFO, "verify done %d extra bytes\n", verify_extra);
jtag_okay("verify done");
}
void handle_flash(const char *name, unsigned addr, unsigned sz)
{
struct ptentry *ptn;
struct ptable *ptable;
void *data = (void *) addr;
unsigned extra = 0;
ptable = flash_get_ptable();
if (ptable == NULL) {
jtag_fail("partition table doesn't exist");
return;
}
ptn = ptable_find(ptable, name);
if (ptn == NULL) {
jtag_fail("unknown partition name");
return;
}
if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
jtag_fail("image is not a boot image");
return;
}
}
if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata") || !strcmp(ptn->name, "persist"))
extra = ((page_size >> 9) * 16);
else
sz = ROUND_TO_PAGE(sz, page_mask);
data = (void *)target_get_scratch_address();
dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
if (flash_write(ptn, extra, data, sz)) {
jtag_fail("flash write failure");
return;
}
dprintf(INFO, "partition '%s' updated\n", ptn->name);
jtag_okay("Done");
enter_critical_section();
platform_uninit_timer();
arch_disable_cache(UCACHE);
arch_disable_mmu();
}
static unsigned char *tmpbuf = 0;
/*XXX*/
void handle_dump(const char *name, unsigned offset)
{
struct ptentry *p;
struct ptable *ptable;
if(tmpbuf == 0) {
tmpbuf = malloc(4096);
}
dprintf(INFO, "dump '%s' partition\n", name);
ptable = flash_get_ptable();
if (ptable == NULL) {
jtag_fail("partition table doesn't exist");
return;
}
p = ptable_find(ptable, name);
if(p == 0) {
jtag_fail("partition not found");
return;
} else {
#if 0
/* XXX reimpl */
if(flash_read_page(p->start * 64, tmpbuf, tmpbuf + 2048)){
jtag_fail("flash_read() failed");
return;
}
#endif
dprintf(INFO, "page %d data:\n", p->start * 64);
hexdump(tmpbuf, 256);
dprintf(INFO, "page %d extra:\n", p->start * 64);
hexdump(tmpbuf, 16);
jtag_okay("done");
enter_critical_section();
platform_uninit_timer();
arch_disable_cache(UCACHE);
arch_disable_mmu();
}
}
void handle_query_load_address(unsigned addr)
{
unsigned *return_addr = (unsigned *)addr;
if (return_addr)
*return_addr = target_get_scratch_address();
jtag_okay("done");
}
void handle_command(const char *cmd, unsigned a0, unsigned a1, unsigned a2)
{
if(startswith(cmd,"flash:")){
handle_flash(cmd + 6, a0, a1);
return;
}
if(startswith(cmd,"dump:")){
handle_dump(cmd + 5, a0);
return;
}
if(startswith(cmd,"loadaddr:")){
handle_query_load_address(a0);
return;
}
jtag_fail("unknown command");
}
void nandwrite_init(void)
{
page_size = flash_page_size();
page_mask = page_size - 1;
jtag_cmd_loop(handle_command);
}
@@ -0,0 +1,6 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/nandwrite.o \
@@ -0,0 +1,249 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <app.h>
#include <debug.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <compiler.h>
#include <platform.h>
#include <dev/pci.h>
#if defined(WITH_LIB_CONSOLE)
#include <lib/console.h>
/*
* enumerates pci devices
*/
static void pci_list(void)
{
pci_location_t state;
uint16_t device_id, vendor_id;
uint8_t header_type;
int busses = 0, devices = 0, lines = 0, devfn, ret;
char c;
printf("Scanning...\n");
for (state.bus = 0; state.bus <= pci_get_last_bus(); state.bus++) {
busses++;
for (devfn = 0; devfn < 256; devfn++) {
state.dev_fn = devfn;
ret = pci_read_config_half(&state, PCI_CONFIG_VENDOR_ID, &vendor_id);
if (ret != _PCI_SUCCESSFUL) goto error;
ret = pci_read_config_half(&state, PCI_CONFIG_DEVICE_ID, &device_id);
if (ret != _PCI_SUCCESSFUL) goto error;
ret = pci_read_config_byte(&state, PCI_CONFIG_HEADER_TYPE, &header_type);
if (ret != _PCI_SUCCESSFUL) goto error;
if (vendor_id != 0xffff) {
printf("%02x:%02x vendor_id=%04x device_id=%04x, header_type=%02x\n", state.bus, state.dev_fn,
vendor_id, device_id, header_type);
devices++;
lines++;
}
if (~header_type & PCI_HEADER_TYPE_MULTI_FN) {
// this is not a multi-function device, so advance to the next device
devfn |= 7;
}
if (lines == 23) {
printf("... press any key to continue, q to quit ...");
while(getc(&c) < 0);
printf("\n");
lines = 0;
if (c == 'q' || c == 'Q') goto quit;
}
}
}
printf("... done. Scanned %d busses, %d device/functions\n", busses, devices);
quit:
return;
error:
printf("Error while reading PCI config space: %02x\n", ret);
}
/*
* a somewhat fugly pci config space examine/modify command. this should probably
* be broken up a bit.
*/
static int pci_config(int argc, const cmd_args *argv)
{
pci_location_t loc;
pci_config_t config;
uint32_t offset;
unsigned int i;
int ret;
if (argc < 5) {
return -1;
}
if (!strcmp(argv[2].str, "dump")) {
loc.bus = atoui(argv[3].str);
loc.dev_fn = atoui(argv[4].str);
for (i=0; i < sizeof(pci_config_t); i++) {
ret = pci_read_config_byte(&loc, i, (uint8_t *) &config + i);
if (ret != _PCI_SUCCESSFUL) goto error;
}
printf("Device at %02x:%02x vendor id=%04x device id=%04x\n", loc.bus,
loc.dev_fn, config.vendor_id, config.device_id);
printf("command=%04x status=%04x pi=%02x sub cls=%02x base cls=%02x\n",
config.command, config.status, config.program_interface,
config.sub_class, config.base_class);
for (i=0; i < 6; i+=2) {
printf("bar%d=%08x bar%d=%08x\n", i, config.base_addresses[i],
i+1, config.base_addresses[i+1]);
}
} else if (!strcmp(argv[2].str, "rb") || !strcmp(argv[2].str, "rh") || !strcmp(argv[2].str, "rw")) {
if (argc != 6) {
return -1;
}
loc.bus = atoui(argv[3].str);
loc.dev_fn = atoui(argv[4].str);
offset = atoui(argv[5].str);
switch (argv[2].str[1]) {
case 'b': {
uint8_t value;
ret = pci_read_config_byte(&loc, offset, &value);
if (ret != _PCI_SUCCESSFUL) goto error;
printf("byte at device %02x:%02x config offset %04x: %02x\n", loc.bus, loc.dev_fn, offset, value);
}
break;
case 'h': {
uint16_t value;
ret = pci_read_config_half(&loc, offset, &value);
if (ret != _PCI_SUCCESSFUL) goto error;
printf("half at device %02x:%02x config offset %04x: %04x\n", loc.bus, loc.dev_fn, offset, value);
}
break;
case 'w': {
uint32_t value;
ret = pci_read_config_word(&loc, offset, &value);
if (ret != _PCI_SUCCESSFUL) goto error;
printf("word at device %02x:%02x config offset %04x: %08x\n", loc.bus, loc.dev_fn, offset, value);
}
break;
}
} else if (!strcmp(argv[2].str, "mb") || !strcmp(argv[2].str, "mh") || !strcmp(argv[2].str, "mw")) {
if (argc != 7) {
return -1;
}
loc.bus = atoui(argv[3].str);
loc.dev_fn = atoui(argv[4].str);
offset = atoui(argv[5].str);
switch (argv[2].str[1]) {
case 'b': {
uint8_t value = atoui(argv[6].str);
ret = pci_write_config_byte(&loc, offset, value);
if (ret != _PCI_SUCCESSFUL) goto error;
printf("byte to device %02x:%02x config offset %04x: %02x\n", loc.bus, loc.dev_fn, offset, value);
}
break;
case 'h': {
uint16_t value = atoui(argv[6].str);
ret = pci_write_config_half(&loc, offset, value);
if (ret != _PCI_SUCCESSFUL) goto error;
printf("half to device %02x:%02x config offset %04x: %04x\n", loc.bus, loc.dev_fn, offset, value);
}
break;
case 'w': {
uint32_t value = atoui(argv[6].str);
ret = pci_write_config_word(&loc, offset, value);
if (ret != _PCI_SUCCESSFUL) goto error;
printf("word to device %02x:%02x config offset %04x: %08x\n", loc.bus, loc.dev_fn, offset, value);
}
break;
}
} else {
return -1;
}
return 0;
error:
printf("Error while reading PCI config space: %02x\n", ret);
return -2;
}
static int pci_cmd(int argc, const cmd_args *argv)
{
if (argc < 2) {
printf("pci commands:\n");
usage:
printf("%s list\n", argv[0].str);
printf("%s config dump <bus> <devfn>\n", argv[0].str);
printf("%s config <rb|rh|rw> <bus> <devfn> <offset>\n", argv[0].str);
printf("%s config <mb|mh|mw> <bus> <devfn> <offset> <value>\n", argv[0].str);
goto out;
}
if (!strcmp(argv[1].str, "list")) {
pci_list();
} else if (!strcmp(argv[1].str, "config")) {
if (pci_config(argc, argv)) {
goto usage;
}
} else {
goto usage;
}
out:
return 0;
}
STATIC_COMMAND_START
{ "pci", "pci toolbox", &pci_cmd },
STATIC_COMMAND_END(pcitests);
#endif
APP_START(pcitests)
APP_END
@@ -0,0 +1,6 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
#INCLUDES += -I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/pci_tests.o
+8
View File
@@ -0,0 +1,8 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULES += \
lib/openssl
OBJS += \
$(LOCAL_DIR)/app.o
@@ -0,0 +1,7 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULES += \
lib/console
OBJS += \
$(LOCAL_DIR)/shell.o
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2009 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <app.h>
#include <debug.h>
#include <lib/console.h>
static void shell_init(const struct app_descriptor *app)
{
console_init();
}
static void shell_entry(const struct app_descriptor *app, void *args)
{
console_start();
}
APP_START(shell)
.init = shell_init,
.entry = shell_entry,
APP_END
@@ -0,0 +1,169 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/arm/cores.h>
.text
.align 2
.global mymemcpy
mymemcpy:
// check for zero length copy or the same pointer
cmp r2, #0
cmpne r1, r0
bxeq lr
// save a few registers for use and the return code (input dst)
stmfd sp!, {r0, r4, r5, lr}
// check for forwards overlap (src > dst, distance < len)
subs r3, r0, r1
cmpgt r2, r3
bgt .L_forwardoverlap
// check for a short copy len.
// 20 bytes is enough so that if a 16 byte alignment needs to happen there is at least a
// wordwise copy worth of work to be done.
cmp r2, #(16+4)
blt .L_bytewise
// see if they are similarly aligned on 4 byte boundaries
eor r3, r0, r1
tst r3, #3
bne .L_bytewise // dissimilarly aligned, nothing we can do (for now)
// check for 16 byte alignment on dst.
// this will also catch src being not 4 byte aligned, since it is similarly 4 byte
// aligned with dst at this point.
tst r0, #15
bne .L_not16bytealigned
// check to see if we have at least 32 bytes of data to copy.
// if not, just revert to wordwise copy
cmp r2, #32
blt .L_wordwise
.L_bigcopy:
// copy 32 bytes at a time. src & dst need to be at least 4 byte aligned,
// and we need at least 32 bytes remaining to copy
// save r6-r7 for use in the big copy
stmfd sp!, {r6-r7}
sub r2, r2, #32 // subtract an extra 32 to the len so we can avoid an extra compare
.L_bigcopy_loop:
ldmia r1!, {r4, r5, r6, r7}
stmia r0!, {r4, r5, r6, r7}
ldmia r1!, {r4, r5, r6, r7}
subs r2, r2, #32
stmia r0!, {r4, r5, r6, r7}
bge .L_bigcopy_loop
// restore r6-r7
ldmfd sp!, {r6-r7}
// see if we are done
adds r2, r2, #32
beq .L_done
// less then 4 bytes left?
cmp r2, #4
blt .L_bytewise
.L_wordwise:
// copy 4 bytes at a time.
// src & dst are guaranteed to be word aligned, and at least 4 bytes are left to copy.
subs r2, r2, #4
.L_wordwise_loop:
ldr r3, [r1], #4
subs r2, r2, #4
str r3, [r0], #4
bge .L_wordwise_loop
// correct the remaining len and test for completion
adds r2, r2, #4
beq .L_done
.L_bytewise:
// simple bytewise copy
ldrb r3, [r1], #1
subs r2, r2, #1
strb r3, [r0], #1
bgt .L_bytewise
.L_done:
// load dst for return and restore r4,r5
#if ARM_ARCH_LEVEL >= 5
ldmfd sp!, {r0, r4, r5, pc}
#else
ldmfd sp!, {r0, r4, r5, lr}
bx lr
#endif
.L_not16bytealigned:
// dst is not 16 byte aligned, so we will copy up to 15 bytes to get it aligned.
// src is guaranteed to be similarly word aligned with dst.
// set the condition flags based on the alignment.
lsl r12, r0, #28
rsb r12, r12, #0
msr CPSR_f, r12 // move into NZCV fields in CPSR
// move as many bytes as necessary to get the dst aligned
ldrvsb r3, [r1], #1 // V set
ldrcsh r4, [r1], #2 // C set
ldreq r5, [r1], #4 // Z set
strvsb r3, [r0], #1
strcsh r4, [r0], #2
streq r5, [r0], #4
ldmmiia r1!, {r3-r4} // N set
stmmiia r0!, {r3-r4}
// fix the remaining len
sub r2, r2, r12, lsr #28
// test to see what we should do now
cmp r2, #32
bge .L_bigcopy
b .L_wordwise
// src and dest overlap 'forwards' or dst > src
.L_forwardoverlap:
// do a bytewise reverse copy for now
add r1, r1, r2
add r0, r0, r2
.L_bytewisereverse:
// simple bytewise reverse copy
ldrb r3, [r1], #-1
subs r2, r2, #1
strb r3, [r0], #-1
bgt .L_bytewisereverse
b .L_done
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/arm/cores.h>
.text
.align 2
/* void *memset(void *s, int c, size_t n); */
.global mymemset
mymemset:
// check for zero length
cmp r2, #0
bxeq lr
// save the original pointer
mov r12, r0
// short memsets aren't worth optimizing
cmp r2, #(32 + 16)
blt .L_bytewise
// fill a 32 bit register with the 8 bit value
and r1, r1, #0xff
orr r1, r1, r1, lsl #8
orr r1, r1, r1, lsl #16
// check for 16 byte alignment
tst r0, #15
bne .L_not16bytealigned
.L_bigset:
// dump some registers to make space for our values
stmfd sp!, { r4-r5 }
// fill a bunch of registers with the set value
mov r3, r1
mov r4, r1
mov r5, r1
// prepare the count register so we can avoid an extra compare
sub r2, r2, #32
// 32 bytes at a time
.L_bigset_loop:
stmia r0!, { r1, r3, r4, r5 }
subs r2, r2, #32
stmia r0!, { r1, r3, r4, r5 }
bge .L_bigset_loop
// restore our dumped registers
ldmfd sp!, { r4-r5 }
// see if we're done
adds r2, r2, #32
beq .L_done
.L_bytewise:
// bytewise memset
subs r2, r2, #1
strb r1, [r0], #1
bgt .L_bytewise
.L_done:
// restore the base pointer as return value
mov r0, r12
bx lr
.L_not16bytealigned:
// dst is not 16 byte aligned, so we will set up to 15 bytes to get it aligned.
// set the condition flags based on the alignment.
lsl r3, r0, #28
rsb r3, r3, #0
msr CPSR_f, r3 // move into NZCV fields in CPSR
// move as many bytes as necessary to get the dst aligned
strvsb r1, [r0], #1 // V set
strcsh r1, [r0], #2 // C set
streq r1, [r0], #4 // Z set
strmi r1, [r0], #4 // N set
strmi r1, [r0], #4 // N set
// fix the remaining len
sub r2, r2, r3, lsr #28
// do the large memset
b .L_bigset
@@ -0,0 +1,6 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/string_tests.o \
$(LOCAL_DIR)/mymemcpy.o \
$(LOCAL_DIR)/mymemset.o
@@ -0,0 +1,285 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <string.h>
#include <malloc.h>
#include <app.h>
#include <platform.h>
#include <kernel/thread.h>
static uint8_t *src;
static uint8_t *dst;
static uint8_t *src2;
static uint8_t *dst2;
#define BUFFER_SIZE (1024*1024)
#define ITERATIONS 16
extern void *mymemcpy(void *dst, const void *src, size_t len);
extern void *mymemset(void *dst, int c, size_t len);
static void *null_memcpy(void *dst, const void *src, size_t len)
{
return dst;
}
static time_t bench_memcpy_routine(void *memcpy_routine(void *, const void *, size_t), size_t srcalign, size_t dstalign)
{
int i;
time_t t0;
t0 = current_time();
for (i=0; i < ITERATIONS; i++) {
memcpy_routine(dst + dstalign, src + srcalign, BUFFER_SIZE);
}
return current_time() - t0;
}
static void bench_memcpy(void)
{
time_t null, libc, mine;
size_t srcalign, dstalign;
printf("memcpy speed test\n");
thread_sleep(200); // let the debug string clear the serial port
for (srcalign = 0; srcalign < 64; ) {
for (dstalign = 0; dstalign < 64; ) {
null = bench_memcpy_routine(&null_memcpy, srcalign, dstalign);
libc = bench_memcpy_routine(&memcpy, srcalign, dstalign);
mine = bench_memcpy_routine(&mymemcpy, srcalign, dstalign);
printf("srcalign %lu, dstalign %lu\n", srcalign, dstalign);
printf(" null memcpy %u msecs\n", null);
printf(" libc memcpy %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
printf(" my memcpy %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
if (dstalign == 0)
dstalign = 1;
else
dstalign <<= 1;
}
if (srcalign == 0)
srcalign = 1;
else
srcalign <<= 1;
}
}
static void fillbuf(void *ptr, size_t len, uint32_t seed)
{
size_t i;
for (i = 0; i < len; i++) {
((char *)ptr)[i] = seed;
seed *= 0x1234567;
}
}
static void validate_memcpy(void)
{
size_t srcalign, dstalign, size;
const size_t maxsize = 256;
printf("testing memcpy for correctness\n");
/*
* do the simple tests to make sure that memcpy doesn't color outside
* the lines for all alignment cases
*/
for (srcalign = 0; srcalign < 64; srcalign++) {
for (dstalign = 0; dstalign < 64; dstalign++) {
// printf("srcalign %zu, dstalign %zu\n", srcalign, dstalign);
for (size = 0; size < maxsize; size++) {
// printf("srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
fillbuf(src, maxsize * 2, 567);
fillbuf(src2, maxsize * 2, 567);
fillbuf(dst, maxsize * 2, 123514);
fillbuf(dst2, maxsize * 2, 123514);
memcpy(dst + dstalign, src + srcalign, size);
mymemcpy(dst2 + dstalign, src2 + srcalign, size);
int comp = memcmp(dst, dst2, maxsize * 2);
if (comp != 0) {
printf("error! srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
}
}
}
}
}
static void validate_memcpy_overlap(void)
{
size_t srcalign, dstalign, size;
const size_t maxsize = 256;
int comp;
printf("testing memcpy for correctness in overlap cases\n");
for (dstalign = 0; dstalign < 64; dstalign++) {
for (size = 0; size < maxsize; size++) {
fillbuf(src, maxsize * 2, 567);
fillbuf(src2, maxsize * 2, 567);
/* Case one will check cpy memory is the same - fwd*/
memcpy(src + dstalign, src, size);
comp = memcmp(src + dstalign, src2, size);
if (comp != 0) {
printf("ERROR (Case1): dstalign %zu, size %zu, ret %d\n", dstalign, size, comp);
}
fillbuf(src, maxsize * 2, 8588485);
fillbuf(src2, maxsize * 2, 8588485);
/* Case two will check cpy memory is the same - bkwd*/
memcpy(src, src + dstalign, size);
comp = memcmp(src, src2 + dstalign, size);
if (comp != 0) {
printf("ERROR (Case2): dstalign %zu, size %zu, ret %d\n", dstalign, size, comp);
}
}
}
}
static time_t bench_memset_routine(void *memset_routine(void *, int, size_t), size_t dstalign)
{
int i;
time_t t0;
t0 = current_time();
for (i=0; i < ITERATIONS; i++) {
memset_routine(dst + dstalign, 0, BUFFER_SIZE);
}
return current_time() - t0;
}
static void bench_memset(void)
{
time_t libc, mine;
size_t dstalign;
printf("memset speed test\n");
thread_sleep(200); // let the debug string clear the serial port
for (dstalign = 0; dstalign < 64; dstalign++) {
libc = bench_memset_routine(&memset, dstalign);
mine = bench_memset_routine(&mymemset, dstalign);
printf("dstalign %lu\n", dstalign);
printf(" libc memset %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
printf(" my memset %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
}
}
static void validate_memset(void)
{
size_t dstalign, size;
int c;
const size_t maxsize = 256;
printf("testing memset for correctness\n");
for (dstalign = 0; dstalign < 64; dstalign++) {
printf("align %zd\n", dstalign);
for (size = 0; size < maxsize; size++) {
for (c = 0; c < 256; c++) {
fillbuf(dst, maxsize * 2, 123514);
fillbuf(dst2, maxsize * 2, 123514);
memset(dst + dstalign, c, size);
mymemset(dst2 + dstalign, c, size);
int comp = memcmp(dst, dst2, maxsize * 2);
if (comp != 0) {
printf("error! align %zu, c %d, size %zu\n", dstalign, c, size);
}
}
}
}
}
#if defined(WITH_LIB_CONSOLE)
#include <lib/console.h>
static int string_tests(int argc, cmd_args *argv)
{
src = memalign(64, BUFFER_SIZE + 256);
dst = memalign(64, BUFFER_SIZE + 256);
src2 = memalign(64, BUFFER_SIZE + 256);
dst2 = memalign(64, BUFFER_SIZE + 256);
printf("src %p, dst %p\n", src, dst);
printf("src2 %p, dst2 %p\n", src2, dst2);
if (argc < 3) {
printf("not enough arguments:\n");
usage:
printf("%s validate <routine>\n", argv[0].str);
printf("%s bench <routine>\n", argv[0].str);
goto out;
}
if (!strcmp(argv[1].str, "validate")) {
if (!strcmp(argv[2].str, "memcpy")) {
validate_memcpy();
} else if (!strcmp(argv[2].str, "memset")) {
validate_memset();
} else if (!strcmp(argv[2].str, "memcpy_overlap")) {
validate_memcpy_overlap();
}
} else if (!strcmp(argv[1].str, "bench")) {
if (!strcmp(argv[2].str, "memcpy")) {
bench_memcpy();
} else if (!strcmp(argv[2].str, "memset")) {
bench_memset();
}
} else {
goto usage;
}
out:
free(src);
free(dst);
free(src2);
free(dst2);
return 0;
}
STATIC_COMMAND_START
{ "string", NULL, &string_tests },
STATIC_COMMAND_END(stringtests);
#endif
APP_START(stringtests)
APP_END
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <pm8x41_adc.h>
#include <debug.h>
void adc_test()
{
uint32_t vadc_chan1;
uint32_t vadc_chan2;
uint16_t iusb = 3250000;
uint16_t ibat = 2500000;
uint16_t batt_id_chan = 49;
uint16_t vbat_sns_chan = 6;
/*
* TEST: Read the voltage on batt_id & vbat_sns channels
*/
vadc_chan1 = pm8x41_adc_channel_read(batt_id_chan);
dprintf(INFO, "The channel [%ud] voltage is :%ud\n",batt_id_chan, vadc_chan1);
vadc_chan2 = pm8x41_adc_channel_read(vbat_sns_chan);
dprintf(INFO, "The channel [%ud] voltage is :%ud\n",vbat_sns_chan, vadc_chan2);
/*
* TEST: Set the IUSB & IBAT max values
*/
if (!pm8x41_iusb_max_config(iusb))
dprintf(INFO, "Iusb max current is set\n");
if (!pm8x41_ibat_max_config(ibat))
dprintf(INFO, "Ibat max current is set\n");
}
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <i2c_qup.h>
#include <blsp_qup.h>
#define EEPROM_HW_I2C_ADDRESS (0x52)
void eeprom_read_test()
{
struct qup_i2c_dev *dev;
char ret[100] = {'\0'};
dev = qup_blsp_i2c_init(BLSP_ID_2, QUP_ID_4, 100000, 19200000);
if (!dev) {
dprintf(CRITICAL, "Failed initializing I2c\n");
return;
}
/* Create a i2c_msg buffer, to read from eprom */
struct i2c_msg msg_buf[] = {
{EEPROM_HW_I2C_ADDRESS, I2C_M_RD, 100, ret}
};
qup_i2c_xfer(dev, msg_buf, 1);
}
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __APP_TESTS_H
#define __APP_TESTS_H
int thread_tests(void);
void printf_tests(void);
#endif
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2011, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include<dev/pm8921_leds.h>
#include<dev/pm8921.h>
void led_tests()
{
uint32_t duty_us, period_us;
/* 50% Duty cycle */
duty_us = 500000;
period_us = 1000000;
/* Configure PM8921_ID_LED_0 from PWM2*/
pm8921_config_led_current(PM8921_ID_LED_0, 2, PWM2, 1);
/* PWM2 for PM8921_ID_LED_0 is LPG 5
* Configure and enable lpg5
*/
pm_set_pwm_config(5, duty_us, period_us, &pmic);
pm_pwm_channel_enable(5, &pmic);
/* Configure and enable lpg0 for panel backlight*/
pm_set_pwm_config(0, duty_us, period_us, &pmic);
pm_pwm_channel_enable(0, &pmic);
mdelay(10000);
/* Configure PM8921_ID_LED_1 also from PWM2*/
pm8921_config_led_current(PM8921_ID_LED_1, 2, PWM2, 1);
mdelay(10000);
/* Disable PM8921_ID_LED_0 */
pm8921_config_led_current(PM8921_ID_LED_0, 2, 2, 0);
/* Turn on GPIO 24 through LPG 0
* Will be reconfigured during display_init
*/
panel_backlight_on_pwm();
mdelay(10000);
/* Disable PM8921_ID_LED_1 */
pm8921_config_led_current(PM8921_ID_LED_1, 2, 2, 0);
}
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <app/tests.h>
#include <debug.h>
void printf_tests(void)
{
printf("printf tests\n");
printf("numbers:\n");
printf("int8: %hhd %hhd %hhd\n", -12, 0, 254);
printf("uint8: %hhu %hhu %hhu\n", -12, 0, 254);
printf("int16: %hd %hd %hd\n", -1234, 0, 1234);
printf("uint16:%hu %hu %hu\n", -1234, 0, 1234);
printf("int: %d %d %d\n", -12345678, 0, 12345678);
printf("uint: %u %u %u\n", -12345678, 0, 12345678);
printf("long: %ld %ld %ld\n", -12345678, 0, 12345678);
printf("ulong: %lu %lu %lu\n", -12345678, 0, 12345678);
printf("long: %D %D %D\n", -12345678, 0, 12345678);
printf("ulong: %U %U %U\n", -12345678, 0, 12345678);
printf("longlong: %lli %lli %lli\n", -12345678LL, 0LL, 12345678LL);
printf("ulonglong: %llu %llu %llu\n", -12345678LL, 0LL, 12345678LL);
printf("size_t: %zd %zd %zd\n", -12345678, 0, 12345678);
printf("usize_t: %zu %zu %zu\n", -12345678, 0, 12345678);
printf("hex:\n");
printf("uint8: %hhx %hhx %hhx\n", -12, 0, 254);
printf("uint16:%hx %hx %hx\n", -1234, 0, 1234);
printf("uint: %x %x %x\n", -12345678, 0, 12345678);
printf("ulong: %lx %lx %lx\n", -12345678, 0, 12345678);
printf("ulong: %X %X %X\n", -12345678, 0, 12345678);
printf("ulonglong: %llx %llx %llx\n", -12345678LL, 0LL, 12345678LL);
printf("usize_t: %zx %zx %zx\n", -12345678, 0, 12345678);
printf("alt/sign:\n");
printf("uint: %#x %#X\n", 0xabcdef, 0xabcdef);
printf("int: %+d %+d\n", 12345678, -12345678);
printf("formatting\n");
printf("int: a%8da\n", 12345678);
printf("int: a%9da\n", 12345678);
printf("int: a%-9da\n", 12345678);
printf("int: a%10da\n", 12345678);
printf("int: a%-10da\n", 12345678);
printf("int: a%09da\n", 12345678);
printf("int: a%010da\n", 12345678);
printf("int: a%6da\n", 12345678);
printf("a%1sa\n", "b");
printf("a%9sa\n", "b");
printf("a%-9sa\n", "b");
printf("a%5sa\n", "thisisatest");
int err;
err = printf("a");
printf(" returned %d\n", err);
err = printf("ab");
printf(" returned %d\n", err);
err = printf("abc");
printf(" returned %d\n", err);
err = printf("abcd");
printf(" returned %d\n", err);
err = printf("abcde");
printf(" returned %d\n", err);
err = printf("abcdef");
printf(" returned %d\n", err);
}
+10
View File
@@ -0,0 +1,10 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
INCLUDES += -I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/tests.o \
$(LOCAL_DIR)/thread_tests.o \
$(LOCAL_DIR)/printf_tests.o \
$(LOCAL_DIR)/i2c_tests.o \
$(LOCAL_DIR)/adc_tests.o
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <app.h>
#include <debug.h>
#include <app/tests.h>
#include <compiler.h>
#if defined(WITH_LIB_CONSOLE)
#include <lib/console.h>
STATIC_COMMAND_START
STATIC_COMMAND("printf_tests", NULL, (console_cmd)&printf_tests)
STATIC_COMMAND("thread_tests", NULL, (console_cmd)&thread_tests)
STATIC_COMMAND_END(tests);
#endif
static void tests_init(const struct app_descriptor *app)
{
}
APP_START(tests)
.init = tests_init,
.flags = 0,
APP_END
@@ -0,0 +1,322 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <rand.h>
#include <app/tests.h>
#include <kernel/thread.h>
#include <kernel/mutex.h>
#include <kernel/event.h>
static int sleep_thread(void *arg)
{
for(;;) {
printf("sleeper %p\n", current_thread);
thread_sleep(rand() % 500);
}
return 0;
}
int sleep_test(void)
{
int i;
for(i=0; i < 16; i++)
thread_resume(thread_create("sleeper", &sleep_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
return 0;
}
static volatile int shared = 0;
static mutex_t m;
static volatile int mutex_thread_count = 0;
static int mutex_thread(void *arg)
{
int i;
const int iterations = 10000;
atomic_add(&mutex_thread_count, 1);
printf("mutex tester thread %p starting up, will go for %d iterations\n", current_thread, iterations);
for (i = 0; i < iterations; i++) {
mutex_acquire(&m);
if (shared != 0)
panic("someone else has messed with the shared data\n");
shared = (int)current_thread;
thread_yield();
shared = 0;
mutex_release(&m);
thread_yield();
}
atomic_add(&mutex_thread_count, -1);
return 0;
}
static int mutex_timeout_thread(void *arg)
{
mutex_t *timeout_mutex = (mutex_t *)arg;
status_t err;
printf("mutex_timeout_thread acquiring mutex %p with 1 second timeout\n", timeout_mutex);
err = mutex_acquire_timeout(timeout_mutex, 1000);
printf("mutex_acquire_timeout returns %d\n", err);
return err;
}
static int mutex_zerotimeout_thread(void *arg)
{
mutex_t *timeout_mutex = (mutex_t *)arg;
status_t err;
printf("mutex_zerotimeout_thread acquiring mutex %p with zero second timeout\n", timeout_mutex);
err = mutex_acquire_timeout(timeout_mutex, 0);
printf("mutex_acquire_timeout returns %d\n", err);
return err;
}
int mutex_test(void)
{
mutex_init(&m);
int i;
for(i=0; i < 5; i++)
thread_resume(thread_create("mutex tester", &mutex_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(1000);
while (mutex_thread_count > 0)
thread_yield();
printf("done with simple mutex tests\n");
printf("testing mutex timeout\n");
mutex_t timeout_mutex;
mutex_init(&timeout_mutex);
mutex_acquire(&timeout_mutex);
for (i=0; i < 2; i++)
thread_resume(thread_create("mutex timeout tester", &mutex_timeout_thread, (void *)&timeout_mutex, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
for (i=0; i < 2; i++)
thread_resume(thread_create("mutex timeout tester", &mutex_zerotimeout_thread, (void *)&timeout_mutex, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(5000);
mutex_release(&timeout_mutex);
printf("done with mutex tests\n");
mutex_destroy(&timeout_mutex);
return 0;
}
static event_t e;
static int event_signaller(void *arg)
{
printf("event signaller pausing\n");
thread_sleep(1000);
// for (;;) {
printf("signalling event\n");
event_signal(&e, true);
printf("done signalling event\n");
thread_yield();
// }
return 0;
}
static int event_waiter(void *arg)
{
printf("event waiter starting\n");
for (;;) {
printf("%p: waiting on event...\n", current_thread);
if (event_wait(&e) < 0) {
printf("%p: event_wait() returned error\n", current_thread);
return -1;
}
printf("%p: done waiting on event...\n", current_thread);
thread_yield();
}
return 0;
}
void event_test(void)
{
/* make sure signalling the event wakes up all the threads */
event_init(&e, false, 0);
thread_resume(thread_create("event signaller", &event_signaller, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 0", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 1", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 2", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 3", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(2000);
event_destroy(&e);
/* make sure signalling the event wakes up precisely one thread */
event_init(&e, false, EVENT_FLAG_AUTOUNSIGNAL);
thread_resume(thread_create("event signaller", &event_signaller, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 0", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 1", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 2", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 3", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(2000);
event_destroy(&e);
}
static int quantum_tester(void *arg)
{
for (;;) {
printf("%p: in this thread. rq %d\n", current_thread, current_thread->remaining_quantum);
}
return 0;
}
void quantum_test(void)
{
thread_resume(thread_create("quantum tester 0", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("quantum tester 1", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("quantum tester 2", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("quantum tester 3", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
}
static event_t context_switch_event;
static event_t context_switch_done_event;
static int context_switch_tester(void *arg)
{
int i;
uint total_count = 0;
const int iter = 100000;
int thread_count = (int)arg;
event_wait(&context_switch_event);
uint count = arch_cycle_count();
for (i = 0; i < iter; i++) {
thread_yield();
}
total_count += arch_cycle_count() - count;
thread_sleep(1000);
printf("took %u cycles to yield %d times, %u per yield, %u per yield per thread\n",
total_count, iter, total_count / iter, total_count / iter / thread_count);
event_signal(&context_switch_done_event, true);
return 0;
}
void context_switch_test(void)
{
event_init(&context_switch_event, false, 0);
event_init(&context_switch_done_event, false, 0);
thread_resume(thread_create("context switch idle", &context_switch_tester, (void *)1, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(100);
event_signal(&context_switch_event, true);
event_wait(&context_switch_done_event);
thread_sleep(100);
event_unsignal(&context_switch_event);
event_unsignal(&context_switch_done_event);
thread_resume(thread_create("context switch 2a", &context_switch_tester, (void *)2, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("context switch 2b", &context_switch_tester, (void *)2, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(100);
event_signal(&context_switch_event, true);
event_wait(&context_switch_done_event);
thread_sleep(100);
event_unsignal(&context_switch_event);
event_unsignal(&context_switch_done_event);
thread_resume(thread_create("context switch 4a", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("context switch 4b", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("context switch 4c", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("context switch 4d", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(100);
event_signal(&context_switch_event, true);
event_wait(&context_switch_done_event);
thread_sleep(100);
}
static volatile int atomic;
static volatile int atomic_count;
static int atomic_tester(void *arg)
{
int add = (int)arg;
int i;
TRACEF("add %d\n", add);
for (i=0; i < 1000000; i++) {
atomic_add(&atomic, add);
}
int old = atomic_add(&atomic_count, -1);
TRACEF("exiting, old count %d\n", old);
return 0;
}
static void atomic_test(void)
{
atomic = 0;
atomic_count = 8;
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
while (atomic_count > 0) {
thread_sleep(1);
}
printf("atomic count == %d (should be zero)\n", atomic);
}
int thread_tests(void)
{
mutex_test();
event_test();
thread_sleep(200);
context_switch_test();
atomic_test();
return 0;
}
+85
View File
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <arch.h>
#include <arch/ops.h>
#include <arch/arm.h>
#include <arch/arm/mmu.h>
#include <platform.h>
#if ARM_CPU_CORTEX_A8
static void set_vector_base(addr_t addr)
{
__asm__ volatile("mcr p15, 0, %0, c12, c0, 0" :: "r" (addr));
}
#endif
void arch_early_init(void)
{
/* turn off the cache */
arch_disable_cache(UCACHE);
/* set the vector base to our exception vectors so we dont need to double map at 0 */
#if ARM_CPU_CORTEX_A8
set_vector_base(MEMBASE);
#endif
#if ARM_WITH_MMU
arm_mmu_init();
#endif
/* turn the cache back on */
arch_enable_cache(UCACHE);
#if ARM_WITH_NEON
/* enable cp10 and cp11 */
uint32_t val;
__asm__ volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (val));
val |= (3<<22)|(3<<20);
__asm__ volatile("mcr p15, 0, %0, c1, c0, 2" :: "r" (val));
/* set enable bit in fpexc */
__asm__ volatile("mrc p10, 7, %0, c8, c0, 0" : "=r" (val));
val |= (1<<30);
__asm__ volatile("mcr p10, 7, %0, c8, c0, 0" :: "r" (val));
#endif
#if ARM_CPU_CORTEX_A8
/* enable the cycle count register */
uint32_t en;
__asm__ volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (en));
en &= ~(1<<3); /* cycle count every cycle */
en |= 1; /* enable all performance counters */
__asm__ volatile("mcr p15, 0, %0, c9, c12, 0" :: "r" (en));
/* enable cycle counter */
en = (1<<31);
__asm__ volatile("mcr p15, 0, %0, c9, c12, 1" :: "r" (en));
#endif
}
void arch_init(void)
{
}
+103
View File
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
/* context switch frame is as follows:
* ulr
* usp
* lr
* r11
* r10
* r9
* r8
* r7
* r6
* r5
* r4
*/
/* arm_context_switch(addr_t *old_sp, addr_t new_sp) */
FUNCTION(arm_context_switch)
/* save all the usual registers + user regs */
/* the spsr is saved and restored in the iframe by exceptions.S */
sub r3, sp, #(11*4) /* can't use sp in user mode stm */
mov r12, lr
stmia r3, { r4-r11, r12, r13, r14 }^
/* save old sp */
str r3, [r0]
/* clear any exlusive locks that the old thread holds */
#if ARM_ISA_ARMV7
/* can clear it directly */
.word 0xf57ff01f // clrex
#elif ARM_ISA_ARMV6
/* have to do a fake strex to clear it */
ldr r0, =strex_spot
strex r3, r2, [r0]
#endif
/* load new regs */
ldmia r1, { r4-r11, r12, r13, r14 }^
mov lr, r12 /* restore lr */
add sp, r1, #(11*4) /* restore sp */
bx lr
.ltorg
FUNCTION(arm_save_mode_regs)
mrs r1, cpsr
#if ARM_ISA_ARMv6
cps #0x11 /* fiq */
str r13, [r0], #4
str r14, [r0], #4
cps #0x12 /* irq */
str r13, [r0], #4
str r14, [r0], #4
cps #0x13 /* svc */
str r13, [r0], #4
str r14, [r0], #4
cps #0x17 /* abt */
str r13, [r0], #4
str r14, [r0], #4
cps #0x1b /* und */
str r13, [r0], #4
str r14, [r0], #4
cps #0x1f /* sys */
str r13, [r0], #4
str r14, [r0], #4
#else
// XXX implement
b .
#endif
msr cpsr_c, r1
bx lr
.data
strex_spot:
.word 0
+405
View File
@@ -0,0 +1,405 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/ops.h>
#include <arch/defines.h>
.text
#if ARM_WITH_CACHE
/* low level cache routines for various cpu families */
#if ARM_CPU_ARM1136 || ARM_CPU_ARM926
/* void arch_disable_cache(uint flags) */
FUNCTION(arch_disable_cache)
mov r12, #0 // zero register
mrs r3, cpsr // save the old interrupt state
#if ARM_ISA_ARMv6
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
#else
orr r3, r3, #(1<<7)
msr cpsr, r3
#endif
.Ldcache_disable:
tst r0, #DCACHE
beq .Licache_disable
mrc p15, 0, r1, c1, c0, 0 // cr1
tst r1, #(1<<2) // is the dcache already disabled?
beq .Licache_disable
bic r1, #(1<<2)
mcr p15, 0, r1, c1, c0, 0 // disable dcache
#if ARM_CPU_ARM1136
mcr p15, 0, r12, c7, c14, 0 // clean & invalidate dcache
#elif ARM_CPU_ARM926
0:
mrc p15, 0, r15, c7, c14, 3 // clean & invalidate dcache
bne 0b
#else
#error whut?
#endif
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
.Licache_disable:
tst r0, #ICACHE
beq .Ldone_disable
mrc p15, 0, r1, c1, c0, 0 // cr1
bic r1, #(1<<12)
mcr p15, 0, r1, c1, c0, 0 // disable icache
mcr p15, 0, r12, c7, c5, 0 // invalidate icache
.Ldone_disable:
msr cpsr, r3
bx lr
/* void arch_enable_cache(uint flags) */
FUNCTION(arch_enable_cache)
mov r12, #0 // zero register
mrs r3, cpsr // save the old interrupt state
#if ARM_ISA_ARMv6
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
#else
orr r3, r3, #(1<<7)
msr cpsr, r3
#endif
.Ldcache_enable:
tst r0, #DCACHE
beq .Licache_enable
mrc p15, 0, r1, c1, c0, 0 // cr1
tst r1, #(1<<2) // is the dcache already enabled?
bne .Licache_enable
mcr p15, 0, r12, c7, c6, 0 // invalidate dcache
orr r1, #(1<<2)
mcr p15, 0, r1, c1, c0, 0 // enable dcache
.Licache_enable:
tst r0, #ICACHE
beq .Ldone_enable
mcr p15, 0, r12, c7, c5, 0 // invalidate icache
mrc p15, 0, r1, c1, c0, 0 // cr1
orr r1, #(1<<12)
mcr p15, 0, r1, c1, c0, 0 // enable icache
.Ldone_enable:
msr cpsr, r3
bx lr
#elif ARM_CPU_CORTEX_A8
/* void arch_disable_cache(uint flags) */
FUNCTION(arch_disable_cache)
stmfd sp!, {r4-r11, lr}
mov r7, r0 // save flags
mrs r12, cpsr // save the old interrupt state
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
.Ldcache_disable:
tst r7, #DCACHE
beq .Licache_disable
mrc p15, 0, r0, c1, c0, 0 // cr1
tst r0, #(1<<2) // is the dcache already disabled?
beq .Ldcache_already_disabled
bic r0, #(1<<2)
// make sure all data operations are completed
dsb
mcr p15, 0, r0, c1, c0, 0 // disable dcache
// make sure previous instruction finishes before we clean and flush
isb
// flush and invalidate the dcache
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl flush_invalidate_cache_v7
b .Ldcache_disable_L2
.Ldcache_already_disabled:
// make sure all of the caches are invalidated
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl invalidate_cache_v7
.Ldcache_disable_L2:
#if ARM_WITH_L2
// disable the L2, if present
mrc p15, 0, r0, c1, c0, 1 // aux cr1
bic r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 // disable L2 dcache
#endif
.Licache_disable:
tst r7, #ICACHE
beq .Ldone_disable
mrc p15, 0, r0, c1, c0, 0 // cr1
bic r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 // disable icache
// make sure previous instruction finishes
isb
.Ldone_disable:
// make sure the icache is always invalidated
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
// make sure that data is in sync
dsb
msr cpsr, r12
ldmfd sp!, {r4-r11, pc}
/* void arch_enable_cache(uint flags) */
FUNCTION(arch_enable_cache)
stmfd sp!, {r4-r11, lr}
mov r7, r0 // save flags
mrs r12, cpsr // save the old interrupt state
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
.Ldcache_enable:
tst r7, #DCACHE
beq .Licache_enable
mrc p15, 0, r0, c1, c0, 0 // cr1
tst r0, #(1<<2) // is the dcache already enabled?
bne .Licache_enable
// invalidate L1 and L2
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl invalidate_cache_v7
#if ARM_WITH_L2
// enable the L2, if present
mrc p15, 0, r0, c1, c0, 1 // aux cr1
orr r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 // enable L2 dcache
#endif
mrc p15, 0, r0, c1, c0, 0 // cr1
orr r0, #(1<<2)
mcr p15, 0, r0, c1, c0, 0 // enable dcache
.Licache_enable:
tst r7, #ICACHE
beq .Ldone_enable
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
mrc p15, 0, r0, c1, c0, 0 // cr1
orr r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 // enable icache
.Ldone_enable:
msr cpsr, r12
ldmfd sp!, {r4-r11, pc}
// flush & invalidate cache routine, trashes r0-r6, r9-r11
flush_invalidate_cache_v7:
DMB
/* from ARMv7 manual, B2-17 */
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
ANDS R3, R0, #0x7000000
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
BEQ .Lfinished
MOV R10, #0
.Loop1:
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
AND R1, R1, #7 // get those 3 bits alone
CMP R1, #2
BLT .Lskip // no cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
.word 0xf57ff06f // ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
AND R2, R1, #0x7 // extract the line length field
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R6, =0x00007FFF
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
.Loop2:
MOV R9, R4 // R9 working copy of the max way size (right aligned)
.Loop3:
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
ORR R11, R11, R6, LSL R2 // factor in the index number
MCR p15, 0, R11, c7, c14, 2 // clean & invalidate by set/way
SUBS R9, R9, #1 // decrement the way number
BGE .Loop3
SUBS R6, R6, #1 // decrement the index
BGE .Loop2
.Lskip:
ADD R10, R10, #2 // increment the cache number
CMP R3, R10
BGT .Loop1
.Lfinished:
mov r10, #0
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
dsb
.word 0xf57ff06f // isb
bx lr
// invalidate cache routine, trashes r0-r6, r9-r11
invalidate_cache_v7:
/* from ARMv7 manual, B2-17 */
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
ANDS R3, R0, #0x7000000
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
BEQ .Lfinished_invalidate
MOV R10, #0
.Loop1_invalidate:
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
AND R1, R1, #7 // get those 3 bits alone
CMP R1, #2
BLT .Lskip_invalidate // no cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
.word 0xf57ff06f // ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
AND R2, R1, #0x7 // extract the line length field
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R6, =0x00007FFF
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
.Loop2_invalidate:
MOV R9, R4 // R9 working copy of the max way size (right aligned)
.Loop3_invalidate:
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
ORR R11, R11, R6, LSL R2 // factor in the index number
MCR p15, 0, R11, c7, c6, 2 // invalidate by set/way
SUBS R9, R9, #1 // decrement the way number
BGE .Loop3_invalidate
SUBS R6, R6, #1 // decrement the index
BGE .Loop2_invalidate
.Lskip_invalidate:
ADD R10, R10, #2 // increment the cache number
CMP R3, R10
BGT .Loop1_invalidate
.Lfinished_invalidate:
mov r10, #0
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
dsb
.word 0xf57ff06f // isb
bx lr
#else
#error unhandled cpu
#endif
#if ARM_CPU_ARM926 || ARM_CPU_ARM1136 || ARM_CPU_CORTEX_A8
/* shared cache flush routines */
/* void arch_flush_cache_range(addr_t start, size_t len); */
FUNCTION(arch_clean_cache_range)
0:
mcr p15, 0, r0, c7, c10, 1 // clean cache to PoC by MVA
add r0, r0, #CACHE_LINE
subs r1, r1, #CACHE_LINE
bhs 0b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
bx lr
/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
FUNCTION(arch_clean_invalidate_cache_range)
0:
mcr p15, 0, r0, c7, c14, 1 // clean & invalidate cache to PoC by MVA
add r0, r0, #CACHE_LINE
subs r1, r1, #CACHE_LINE
bhs 0b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
bx lr
/* void arch_invalidate_cache_range(addr_t start, size_t len); */
FUNCTION(arch_invalidate_cache_range)
0:
/* invalidate cache line */
mcr p15, 0, r0, c7, c6, 1
add r0, r0, #CACHE_LINE
subs r1, r1, #CACHE_LINE
bhs 0b
mov r0, #0
/* data sync barrier (formerly drain write buffer*/
mcr p15, 0, r0, c7, c10, 4
bx lr
/* void arch_sync_cache_range(addr_t start, size_t len); */
FUNCTION(arch_sync_cache_range)
push { r14 }
bl arch_clean_cache_range
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
pop { pc }
#else
#error unhandled cpu
#endif
#else
/* no cache */
FUNCTION(arch_disable_cache)
bx lr
FUNCTION(arch_enable_cache)
bx lr
FUNCTION(arch_clean_cache_range)
bx lr
FUNCTION(arch_clean_invalidate_cache_range)
bx lr
FUNCTION(arch_sync_cache_range)
bx lr
#endif // ARM_WITH_CACHE
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
@@ -0,0 +1,39 @@
$(BUILDDIR)/%.o: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(THUMBCFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(THUMBCFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
# to override thumb setting, mark the .o file as .Ao
$(BUILDDIR)/%.Ao: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.Ao: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
# assembly is always compiled in ARM mode at the moment
$(BUILDDIR)/%.Ao: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
ifeq ($(ENABLE_TRUSTZONE), 1)
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) -DENABLE_TRUSTZONE $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
else
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
endif
+189
View File
@@ -0,0 +1,189 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define DSB .byte 0x4f, 0xf0, 0x7f, 0xf5
#define ISB .byte 0x6f, 0xf0, 0x7f, 0xf5
.section ".text.boot"
.globl _start
_start:
b reset
b arm_undefined
b arm_syscall
b arm_prefetch_abort
b arm_data_abort
b arm_reserved
b arm_irq
b arm_fiq
reset:
#ifdef ENABLE_TRUSTZONE
/*Add reference to TZ symbol so linker includes it in final image */
ldr r7, =_binary_tzbsp_tzbsp_bin_start
#endif
/* do some cpu setup */
#if ARM_WITH_CP15
/* Read SCTLR */
mrc p15, 0, r0, c1, c0, 0
/* XXX this is currently for arm926, revist with armv6 cores */
/* new thumb behavior, low exception vectors, i/d cache disable, mmu disabled */
bic r0, r0, #(1<<15| 1<<13 | 1<<12)
bic r0, r0, #(1<<2 | 1<<0)
/* enable alignment faults */
orr r0, r0, #(1<<1)
/* Write SCTLR */
mcr p15, 0, r0, c1, c0, 0
#ifdef ENABLE_TRUSTZONE
/*nkazi: not needed ? Setting VBAR to location of new vector table : 0x80000 */
ldr r0, =0x00080000
mcr p15, 0, r0, c12, c0, 0
#endif
#endif
#if WITH_CPU_EARLY_INIT
/* call platform/arch/etc specific init code */
#ifndef ENABLE_TRUSTZONE
/* Not needed when TrustZone is the first bootloader that runs.*/
bl __cpu_early_init
#endif
/* declare return address as global to avoid using stack */
.globl _cpu_early_init_complete
_cpu_early_init_complete:
#endif
#if (!ENABLE_NANDWRITE)
#if WITH_CPU_WARM_BOOT
ldr r0, warm_boot_tag
cmp r0, #1
/* if set, warm boot */
ldreq pc, =BASE_ADDR
mov r0, #1
str r0, warm_boot_tag
#endif
#endif
/* see if we need to relocate */
mov r0, pc
sub r0, r0, #(.Laddr - _start)
.Laddr:
ldr r1, =_start
cmp r0, r1
beq .Lstack_setup
/* we need to relocate ourselves to the proper spot */
ldr r2, =__data_end
.Lrelocate_loop:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r1, r2
bne .Lrelocate_loop
/* we're relocated, jump to the right address */
ldr r0, =.Lstack_setup
bx r0
.ltorg
#if WITH_CPU_WARM_BOOT
warm_boot_tag:
.word 0
#endif
.Lstack_setup:
/* set up the stack for irq, fiq, abort, undefined, system/user, and lastly supervisor mode */
mrs r0, cpsr
bic r0, r0, #0x1f
ldr r2, =abort_stack_top
orr r1, r0, #0x12 // irq
msr cpsr_c, r1
ldr r13, =irq_save_spot /* save a pointer to a temporary dumping spot used during irq delivery */
orr r1, r0, #0x11 // fiq
msr cpsr_c, r1
mov sp, r2
orr r1, r0, #0x17 // abort
msr cpsr_c, r1
mov sp, r2
orr r1, r0, #0x1b // undefined
msr cpsr_c, r1
mov sp, r2
orr r1, r0, #0x1f // system
msr cpsr_c, r1
mov sp, r2
orr r1, r0, #0x13 // supervisor
msr cpsr_c, r1
mov sp, r2
/* copy the initialized data segment out of rom if necessary */
ldr r0, =__data_start_rom
ldr r1, =__data_start
ldr r2, =__data_end
cmp r0, r1
beq .L__do_bss
.L__copy_loop:
cmp r1, r2
ldrlt r3, [r0], #4
strlt r3, [r1], #4
blt .L__copy_loop
.L__do_bss:
/* clear out the bss */
ldr r0, =__bss_start
ldr r1, =_end
mov r2, #0
.L__bss_loop:
cmp r0, r1
strlt r2, [r0], #4
blt .L__bss_loop
#ifdef ARM_CPU_CORTEX_A8
DSB
ISB
#endif
bl kmain
b .
.ltorg
.bss
.align 2
/* the abort stack is for unrecoverable errors.
* also note the initial working stack is set to here.
* when the threading system starts up it'll switch to a new
* dynamically allocated stack, so we don't need it for very long
*/
abort_stack:
.skip 1024
abort_stack_top:
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2008 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
.global dcc_putc
.global dcc_getc
#if defined(ARM_ISA_ARMV6) || defined(ARM_ISA_ARMV7)
dcc_getc:
mrc 14, 0, r0, c0, c1, 0
tst r0, #(1 << 30)
moveq r0, #-1
mrcne 14, 0, r0, c0, c5, 0
bx lr
dcc_putc:
mrc 14, 0, r15, c0, c1, 0
mcrcc 14, 0, r0, c0, c5, 0
movcc r0, #0
movcs r0, #-1
bx lr
#endif
@@ -0,0 +1,132 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
FUNCTION(arm_undefined)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_undefined_handler
b .
FUNCTION(arm_syscall)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_syscall_handler
b .
FUNCTION(arm_prefetch_abort)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_prefetch_abort_handler
b .
FUNCTION(arm_data_abort)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_data_abort_handler
b .
FUNCTION(arm_reserved)
b .
FUNCTION(arm_irq)
/* XXX only deals with interrupting supervisor mode */
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
stmia r13, { r4-r6 }
mov r4, r13
sub r5, lr, #4
mrs r6, spsr
/* move into supervisor mode. irq/fiq disabled */
msr cpsr_c, #(3<<6 | 0x13)
/* save the return address */
stmfd sp!, { r5 }
/* save C trashed regs, supervisor lr */
stmfd sp!, { r0-r3, r12, lr }
/* save spsr */
stmfd sp!, { r6 }
/* restore r4-r6 */
ldmia r4, { r4-r6 }
/* increment the global critical section count */
ldr r1, =critical_section_count
ldr r0, [r1]
add r0, r0, #1
str r0, [r1]
/* call into higher level code */
mov r0, sp /* iframe */
bl platform_irq
/* reschedule if the handler returns nonzero */
cmp r0, #0
blne thread_preempt
/* decrement the global critical section count */
ldr r1, =critical_section_count
ldr r0, [r1]
sub r0, r0, #1
str r0, [r1]
/* restore spsr */
ldmfd sp!, { r0 }
msr spsr_cxsf, r0
/* restore back to where we came from */
ldmfd sp!, { r0-r3, r12, lr, pc }^
.bss
.align 2
.global irq_save_spot
irq_save_spot:
.word 0 /* r4 */
.word 0 /* r5 */
.word 0 /* r6 */
.text
FUNCTION(arm_fiq)
sub lr, lr, #4
stmfd sp!, { r0-r3, r12, lr }
bl platform_fiq
ldmfd sp!, { r0-r3, r12, pc }^
.ltorg
+91
View File
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <arch/arm.h>
#include <kernel/thread.h>
static void dump_fault_frame(struct arm_fault_frame *frame)
{
dprintf(CRITICAL, "r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n", frame->r[0], frame->r[1], frame->r[2], frame->r[3]);
dprintf(CRITICAL, "r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", frame->r[4], frame->r[5], frame->r[6], frame->r[7]);
dprintf(CRITICAL, "r8 0x%08x r9 0x%08x r10 0x%08x r11 0x%08x\n", frame->r[8], frame->r[9], frame->r[10], frame->r[11]);
dprintf(CRITICAL, "r12 0x%08x usp 0x%08x ulr 0x%08x pc 0x%08x\n", frame->r[12], frame->usp, frame->ulr, frame->pc);
dprintf(CRITICAL, "spsr 0x%08x\n", frame->spsr);
struct arm_mode_regs regs;
arm_save_mode_regs(&regs);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_FIQ) ? '*' : ' ', "fiq", regs.fiq_r13, regs.fiq_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_IRQ) ? '*' : ' ', "irq", regs.irq_r13, regs.irq_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SVC) ? '*' : ' ', "svc", regs.svc_r13, regs.svc_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_UND) ? '*' : ' ', "und", regs.und_r13, regs.und_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SYS) ? '*' : ' ', "sys", regs.sys_r13, regs.sys_r14);
// dump the bottom of the current stack
addr_t stack;
switch (frame->spsr & MODE_MASK) {
case MODE_FIQ: stack = regs.fiq_r13; break;
case MODE_IRQ: stack = regs.irq_r13; break;
case MODE_SVC: stack = regs.svc_r13; break;
case MODE_UND: stack = regs.und_r13; break;
case MODE_SYS: stack = regs.sys_r13; break;
default:
stack = 0;
}
if (stack != 0) {
dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
hexdump((void *)stack, 128);
}
}
static void exception_die(struct arm_fault_frame *frame, int pc_off, const char *msg)
{
inc_critical_section();
frame->pc += pc_off;
dprintf(CRITICAL, msg);
dump_fault_frame(frame);
halt();
for(;;);
}
void arm_syscall_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "unhandled syscall, halting\n");
}
void arm_undefined_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "undefined abort, halting\n");
}
void arm_data_abort_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -8, "data abort, halting\n");
}
void arm_prefetch_abort_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "prefetch abort, halting\n");
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARM_ARCH_THREAD_H
#define __ARM_ARCH_THREAD_H
struct arch_thread {
vaddr_t sp;
};
#endif
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_H
#define __ARCH_ARM_H
#include <sys/types.h>
#include <arch/arm/cores.h>
#if defined(__cplusplus)
extern "C" {
#endif
void arm_context_switch(vaddr_t *old_sp, vaddr_t new_sp);
static inline uint32_t read_cpsr() {
uint32_t cpsr;
__asm__ volatile("mrs %0, cpsr" : "=r" (cpsr));
return cpsr;
}
struct arm_iframe {
uint32_t spsr;
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr;
uint32_t pc;
};
struct arm_fault_frame {
uint32_t spsr;
uint32_t usp;
uint32_t ulr;
uint32_t r[13];
uint32_t pc;
};
#define MODE_MASK 0x1f
#define MODE_USR 0x10
#define MODE_FIQ 0x11
#define MODE_IRQ 0x12
#define MODE_SVC 0x13
#define MODE_MON 0x16
#define MODE_ABT 0x17
#define MODE_UND 0x1b
#define MODE_SYS 0x1f
struct arm_mode_regs {
uint32_t fiq_r13, fiq_r14;
uint32_t irq_r13, irq_r14;
uint32_t svc_r13, svc_r14;
uint32_t abt_r13, abt_r14;
uint32_t und_r13, und_r14;
uint32_t sys_r13, sys_r14;
};
void arm_save_mode_regs(struct arm_mode_regs *regs);
uint32_t arm_read_cr1(void);
void arm_write_cr1(uint32_t val);
uint32_t arm_read_cr1_aux(void);
void arm_write_cr1_aux(uint32_t val);
void arm_write_ttbr(uint32_t val);
void arm_write_dacr(uint32_t val);
void arm_invalidate_tlb(void);
#if defined(__cplusplus)
}
#endif
#endif
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARM_CORES_H
#define __ARM_CORES_H
/*
* make the gcc built in define a little easier to deal with
* to decide what core it is generating code for
*
* ARM_ARCH_LEVEL gets assigned a numeric value of the general family
*
* ARM_ARCH_* gets defined for each feature recursively
*/
#if defined(__ARM_ARCH_7M__)
#define ARM_ARCH_7M 1
#endif
#if defined(__ARM_ARCH_7R__)
#define ARM_ARCH_7R 1
#endif
#if defined(__ARM_ARCH_7A__) || defined(ARM_ARCH_7R)
#define ARM_ARCH_7A 1
#endif
#if defined(__ARM_ARCH_7__) || defined(ARM_ARCH_7A) || defined(ARM_ARCH_7M)
#define ARM_ARCH_7 1
#ifndef ARM_ARCH_LEVEL
#define ARM_ARCH_LEVEL 7
#endif
#endif
#if defined(__ARM_ARCH_6M__)
#define ARM_ARCH_6M 1
#endif
#if defined(__ARM_ARCH_6T2__) || defined(ARM_ARCH_7)
#define ARM_ARCH_6T2 1
#endif
#if defined(__ARM_ARCH_6ZK__)
#define ARM_ARCH_6ZK 1
#endif
#if defined(__ARM_ARCH_6Z__) || defined(ARM_ARCH_6ZK)
#define ARM_ARCH_6Z 1
#endif
#if defined(__ARM_ARCH_6K__) || defined(ARM_ARCH_6ZK) || defined(ARM_ARCH_7)
#define ARM_ARCH_6K 1
#endif
#if defined(__ARM_ARCH_6J__)
#define ARM_ARCH_6J 1
#endif
#if defined(__ARM_ARCH_6__) || defined(ARM_ARCH_6J) || defined(ARM_ARCH_6K) || defined(ARM_ARCH_6Z) || defined(ARM_ARCH_6T2) || defined(ARM_ARCH_6M)
#define ARM_ARCH_6 1
#ifndef ARM_ARCH_LEVEL
#define ARM_ARCH_LEVEL 6
#endif
#endif
#if defined(__ARM_ARCH_5TEJ__)
#define ARM_ARCH_5TEJ 1
#endif
#if defined(__ARM_ARCH_5TE__) || defined(ARM_ARCH_5TEJ) || defined(ARM_ARCH_6)
#define ARM_ARCH_5TE 1
#endif
#if defined(__ARM_ARCH_5E__) || defined(ARM_ARCH_5TE)
#define ARM_ARCH_5E 1
#endif
#if defined(__ARM_ARCH_5T__) || defined(ARM_ARCH_5TE)
#define ARM_ARCH_5T 1
#endif
#if defined(__ARM_ARCH_5__) || defined(ARM_ARCH_5E) || defined(ARM_ARCH_5T)
#define ARM_ARCH_5 1
#ifndef ARM_ARCH_LEVEL
#define ARM_ARCH_LEVEL 5
#endif
#endif
#if defined(__ARM_ARCH_4T__) || defined(ARM_ARCH_5T)
#define ARM_ARCH_4T 1
#endif
#if defined(__ARM_ARCH_4__) || defined(ARM_ARCH_4T) || defined(ARM_ARCH_5)
#define ARM_ARCH_4 1
#ifndef ARM_ARCH_LEVEL
#define ARM_ARCH_LEVEL 4
#endif
#endif
#if 0
/* test */
#if ARM_ARCH_LEVEL >= 7
#warning ARM_ARCH_LEVEL >= 7
#endif
#if ARM_ARCH_LEVEL >= 6
#warning ARM_ARCH_LEVEL >= 6
#endif
#if ARM_ARCH_LEVEL >= 5
#warning ARM_ARCH_LEVEL >= 5
#endif
#if ARM_ARCH_LEVEL >= 4
#warning ARM_ARCH_LEVEL >= 4
#endif
#endif
#endif
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2008 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_DCC_H
#define __ARCH_ARM_DCC_H
/* returns < 0 if no data available */
int dcc_getc(void);
/* returns < 0 if output register was already full */
int dcc_putc(unsigned c);
#endif
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_MMU_H
#define __ARCH_ARM_MMU_H
#include <sys/types.h>
#if defined(__cplusplus)
extern "C" {
#endif
void arm_mmu_init(void);
#if defined(ARM_ISA_ARMV6) | defined(ARM_ISA_ARMV7)
/* C, B and TEX[2:0] encodings without TEX remap */
/* TEX | CB */
#define MMU_MEMORY_TYPE_STRONGLY_ORDERED ((0x0 << 12) | (0x0 << 2))
#define MMU_MEMORY_TYPE_DEVICE_SHARED ((0x0 << 12) | (0x1 << 2))
#define MMU_MEMORY_TYPE_DEVICE_NON_SHARED ((0x2 << 12) | (0x0 << 2))
#define MMU_MEMORY_TYPE_NORMAL ((0x1 << 12) | (0x0 << 2))
#define MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH ((0x0 << 12) | (0x2 << 2))
#define MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_NO_ALLOCATE ((0x0 << 12) | (0x3 << 2))
#define MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_ALLOCATE ((0x1 << 12) | (0x3 << 2))
#define MMU_MEMORY_AP_NO_ACCESS (0x0 << 10)
#define MMU_MEMORY_AP_READ_ONLY (0x7 << 10)
#define MMU_MEMORY_AP_READ_WRITE (0x3 << 10)
#define MMU_MEMORY_XN (0x1 << 4)
#else
#error "MMU implementation needs to be updated for this ARM architecture"
#endif
void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags);
#if defined(__cplusplus)
}
#endif
#endif
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_OPS_H
#define __ARHC_ARM_OPS_H
#if 0
#include <compiler.h>
#ifndef ASSEMBLY
#if ARM_ISA_ARMV7 || ARM_ISA_ARMV6
// override of some routines
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
{
__asm__("cpsie i");
}
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
{
__asm__("cpsid i");
}
#endif
#endif
#endif
#endif
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_CPU_H
#define __ARCH_CPU_H
/* arm specific stuff */
#define PAGE_SIZE 4096
#if defined(ARM_CPU_ARM1136)
#define CACHE_LINE 32
#elif defined(ARM_CPU_CORE_A5)
#define CACHE_LINE 32
#elif defined(ARM_CPU_CORE_SCORPION)
#define CACHE_LINE 32
#elif defined(ARM_CPU_CORE_KRAIT) || defined(ARM_CPU_CORE_A7)
#define CACHE_LINE 64
#else
#error unknown cpu
#endif
#define IS_CACHE_LINE_ALIGNED(addr) !((uint32_t) (addr) & (CACHE_LINE - 1))
#endif
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <sys/types.h>
#include <compiler.h>
#include <arch.h>
#include <arch/arm.h>
#include <arch/arm/mmu.h>
#if ARM_WITH_MMU
#define MB (1024*1024)
/* the location of the table may be brought in from outside */
#if WITH_EXTERNAL_TRANSLATION_TABLE
#if !defined(MMU_TRANSLATION_TABLE_ADDR)
#error must set MMU_TRANSLATION_TABLE_ADDR in the make configuration
#endif
static uint32_t *tt = (void *)MMU_TRANSLATION_TABLE_ADDR;
#else
/* the main translation table */
static uint32_t tt[4096] __ALIGNED(16384);
#endif
void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags)
{
int index;
/* Get the index into the translation table */
index = vaddr / MB;
/* Set the entry value:
* (2<<0): Section entry
* (0<<5): Domain = 0
* flags: TEX, CB and AP bit settings provided by the caller.
*/
tt[index] = (paddr & ~(MB-1)) | (0<<5) | (2<<0) | flags;
arm_invalidate_tlb();
}
void arm_mmu_init(void)
{
int i;
/* set some mmu specific control bits:
* access flag disabled, TEX remap disabled, mmu disabled
*/
arm_write_cr1(arm_read_cr1() & ~((1<<29)|(1<<28)|(1<<0)));
if (platform_use_identity_mmu_mappings())
{
/* set up an identity-mapped translation table with
* strongly ordered memory type and read/write access.
*/
for (i=0; i < 4096; i++) {
arm_mmu_map_section(i * MB,
i * MB,
MMU_MEMORY_TYPE_STRONGLY_ORDERED | MMU_MEMORY_AP_READ_WRITE);
}
}
platform_init_mmu_mappings();
/* set up the translation table base */
arm_write_ttbr((uint32_t)tt);
/* set up the domain access register */
arm_write_dacr(0x00000001);
/* turn on the mmu */
arm_write_cr1(arm_read_cr1() | 0x1);
}
void arch_disable_mmu(void)
{
arm_write_cr1(arm_read_cr1() & ~(1<<0));
arm_invalidate_tlb();
}
#endif // ARM_WITH_MMU
+285
View File
@@ -0,0 +1,285 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
.text
/* void arch_enable_ints(void); */
FUNCTION(arch_enable_ints)
mrs r0, cpsr
bic r0, r0, #(1<<7) /* clear the I bit */
msr cpsr_c, r0
bx lr
/* void arch_disable_ints(void); */
FUNCTION(arch_disable_ints)
mrs r0, cpsr
orr r0, r0, #(1<<7)
msr cpsr_c, r0
bx lr
/* int atomic_swap(int *ptr, int val); */
FUNCTION(atomic_swap)
swp r0, r2, [r1]
bx lr
/* int atomic_add(int *ptr, int val); */
FUNCTION(atomic_add)
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
/* use load/store exclusive */
.L_loop_add:
ldrex r12, [r0]
add r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .L_loop_add
/* save old value */
mov r0, r12
bx lr
#else
/* disable interrupts, do the add, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the add, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
add r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
/* uint64_t atomic_dw_read(uint32_t rd_addr,
* uint32_t st_addr_lo, uint32_t st_addr_hi);
*/
/* Reads a double word from memory atomically */
FUNCTION(atomic_dw_read)
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
stmfd sp!, {r4-r5}
/* use load/store exclusive */
ldrexd r4, [r0]
str r4, [r1]
str r5, [r2]
/* Restore registers */
ldmfd sp!, {r4-r5}
bx lr
#else
stmfd sp!, {r4-r5}
/* disable interrupts, do read, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do memory read, return the double word read */
ldr r4, [r0]
ldr r5, [r0, #4]
str r4, [r1]
str r5, [r2]
/* restore interrupts */
msr cpsr_c, r12
/* restore registers */
ldmfd sp!, {r4-r5}
bx lr
#endif
/* int atomic_and(int *ptr, int val); */
FUNCTION(atomic_and)
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
/* use load/store exclusive */
.L_loop_and:
ldrex r12, [r0]
and r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .L_loop_and
/* save old value */
mov r0, r12
bx lr
#else
/* disable interrupts, do the and, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the and, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
and r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
/* int atomic_or(int *ptr, int val); */
FUNCTION(atomic_or)
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
/* use load/store exclusive */
.L_loop_or:
ldrex r12, [r0]
orr r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .L_loop_or
/* save old value */
mov r0, r12
bx lr
#else
/* disable interrupts, do the or, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the or, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
orr r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
/* void arch_idle(); */
FUNCTION(arch_idle)
#if ARM_CPU_CORTEX_A8
.word 0xe320f003 /* wfi */
#elif PLATFORM_MSM7K
/* TODO: safely handle wfi */
#elif ARM_CPU_ARM1136 || ARM_CPU_ARM926
mov r0, #0
mcr p15, 0, r0, c7, c0, #4
#elif ARM_CPU_ARM7
/* nothing to do here */
#else
#error unknown cpu
#endif
bx lr
/* uint32_t arm_read_cr1(void) */
FUNCTION(arm_read_cr1)
mrc p15, 0, r0, c1, c0, 0
bx lr
/* void arm_write_cr1(uint32_t val) */
FUNCTION(arm_write_cr1)
mcr p15, 0, r0, c1, c0, 0
bx lr
/* uint32_t arm_read_cr1_aux(void) */
FUNCTION(arm_read_cr1_aux)
mrc p15, 0, r0, c1, c0, 1
bx lr
/* void arm_write_cr1_aux(uint32_t val) */
FUNCTION(arm_write_cr1_aux)
mcr p15, 0, r0, c1, c0, 1
bx lr
/* void arm_write_ttbr(uint32_t val) */
FUNCTION(arm_write_ttbr)
mcr p15, 0, r0, c2, c0, 0
bx lr
/* void arm_write_dacr(uint32_t val) */
FUNCTION(arm_write_dacr)
mcr p15, 0, r0, c3, c0, 0
bx lr
/* void arm_invalidate_tlb(void) */
FUNCTION(arm_invalidate_tlb)
mov r0, #0
mcr p15, 0, r0, c8, c7, 0
bx lr
/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
FUNCTION(arch_switch_stacks_and_call)
mov sp, r1
bx r0
/*void dmb(void) */
FUNCTION(dmb)
#if ARM_CPU_CORTEX_A8
dmb sy
#elif ARM_CPU_ARM1136
mov r0, #0
mcr p15, 0, r0, c7, c10, 5
#endif
bx lr
/*void isb(void) */
FUNCTION(isb)
#if ARM_CPU_CORTEX_A8
isb sy
#elif ARM_CPU_ARM1136
mov r0, #0
mcr p15, 0, r0, c7, c5, 4
#endif
bx lr
/*void dsb(void) */
FUNCTION(dsb)
#if ARM_CPU_CORTEX_A8
dsb sy
#elif ARM_CPU_ARM1136
mov r0, #0
mcr p15, 0, r0, c7, c10, 4
#endif
bx lr
/* uint32_t arm_read_cycle_count(void); */
FUNCTION(arm_read_cycle_count)
/* uint32_t arch_cycle_count(void); */
FUNCTION(arch_cycle_count)
#if ARM_CPU_CORTEX_A8
mrc p15, 0, r0, c9, c13, 0
#else
mov r0, #0
#endif
bx lr
+154
View File
@@ -0,0 +1,154 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
# can override this in local.mk
ENABLE_THUMB?=true
DEFINES += \
ARM_CPU_$(ARM_CPU)=1
# do set some options based on the cpu core
HANDLED_CORE := false
ifeq ($(ARM_CPU),cortex-a8)
DEFINES += \
ARM_WITH_CP15=1 \
ARM_WITH_MMU=1 \
ARM_ISA_ARMv7=1 \
ARM_WITH_VFP=1 \
ARM_WITH_NEON=1 \
ARM_WITH_THUMB=1 \
ARM_WITH_THUMB2=1 \
ARM_WITH_CACHE=1 \
ARM_WITH_L2=1
CFLAGS += -mcpu=$(ARM_CPU)
#CFLAGS += -mcpu=arm1136jf-s # compiler doesn't understand cortex yet
HANDLED_CORE := true
#CFLAGS += -mfpu=vfp -mfloat-abi=softfp
endif
ifeq ($(ARM_CPU),arm1136j-s)
DEFINES += \
ARM_WITH_CP15=1 \
ARM_WITH_MMU=1 \
ARM_ISA_ARMv6=1 \
ARM_WITH_THUMB=1 \
ARM_WITH_CACHE=1 \
ARM_CPU_ARM1136=1
CFLAGS += -mcpu=$(ARM_CPU)
HANDLED_CORE := true
endif
ifeq ($(ARM_CPU),arm1176jzf-s)
DEFINES += \
ARM_WITH_CP15=1 \
ARM_WITH_MMU=1 \
ARM_ISA_ARMv6=1 \
ARM_WITH_VFP=1 \
ARM_WITH_THUMB=1 \
ARM_WITH_CACHE=1 \
ARM_CPU_ARM1136=1
CFLAGS += -mcpu=$(ARM_CPU)
HANDLED_CORE := true
endif
ifeq ($(ARM_CPU),arm926ej-s)
DEFINES += \
ARM_WITH_CP15=1 \
ARM_WITH_MMU=1 \
ARM_ISA_ARMv5E=1 \
ARM_WITH_THUMB=1 \
ARM_WITH_CACHE=1 \
ARM_CPU_ARM9=1 \
ARM_CPU_ARM926=1
CFLAGS += -mcpu=$(ARM_CPU)
HANDLED_CORE := true
endif
ifeq ($(ARM_CPU),arm7tdmi)
DEFINES += \
ARM_ISA_ARMv4=1 \
ARM_WITH_THUMB=1 \
ARM_CPU_ARM7=1
CFLAGS += -mcpu=$(ARM_CPU)
HANDLED_CORE := true
endif
ifneq ($(HANDLED_CORE),true)
$(warning $(LOCAL_DIR)/rules.mk doesnt have logic for arm core $(ARM_CPU))
$(warning this is likely to be broken)
endif
THUMBCFLAGS :=
THUMBINTERWORK :=
ifeq ($(ENABLE_THUMB),true)
THUMBCFLAGS := -mthumb -D__thumb__
THUMBINTERWORK := -mthumb-interwork
endif
INCLUDES += \
-I$(LOCAL_DIR)/include
BOOTOBJS += \
$(LOCAL_DIR)/crt0.o
OBJS += \
$(LOCAL_DIR)/arch.Ao \
$(LOCAL_DIR)/asm.o \
$(LOCAL_DIR)/cache.o \
$(LOCAL_DIR)/cache-ops.o \
$(LOCAL_DIR)/ops.o \
$(LOCAL_DIR)/exceptions.o \
$(LOCAL_DIR)/faults.o \
$(LOCAL_DIR)/mmu.o \
$(LOCAL_DIR)/thread.o \
$(LOCAL_DIR)/dcc.o
# set the default toolchain to arm eabi and set a #define
TOOLCHAIN_PREFIX ?= arm-eabi-
ifeq ($(TOOLCHAIN_PREFIX),arm-none-linux-gnueabi-)
# XXX test for EABI better than this
# eabi compilers dont need this
THUMBINTERWORK:=
endif
CFLAGS += $(THUMBINTERWORK)
# make sure some bits were set up
MEMVARS_SET := 0
ifneq ($(MEMBASE),)
MEMVARS_SET := 1
endif
ifneq ($(MEMSIZE),)
MEMVARS_SET := 1
endif
ifeq ($(MEMVARS_SET),0)
$(error missing MEMBASE or MEMSIZE variable, please set in target rules.mk)
endif
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) $(THUMBCFLAGS) -print-libgcc-file-name)
#$(info LIBGCC = $(LIBGCC))
# potentially generated files that should be cleaned out with clean make rule
GENERATED += \
$(BUILDDIR)/system-onesegment.ld \
$(BUILDDIR)/system-twosegment.ld
# rules for generating the linker scripts
$(BUILDDIR)/trustzone-test-system-onesegment.ld: $(LOCAL_DIR)/trustzone-test-system-onesegment.ld
@echo generating $@
@$(MKDIR)
$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/;s/%ROMLITE_PREFLASHED_DATA%/$(ROMLITE_PREFLASHED_DATA)/" < $< > $@
$(BUILDDIR)/trustzone-system-onesegment.ld: $(LOCAL_DIR)/trustzone-system-onesegment.ld
@echo generating $@
@$(MKDIR)
$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
$(BUILDDIR)/system-onesegment.ld: $(LOCAL_DIR)/system-onesegment.ld
@echo generating $@
@$(MKDIR)
$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
$(BUILDDIR)/system-twosegment.ld: $(LOCAL_DIR)/system-twosegment.ld
@echo generating $@
@$(MKDIR)
$(NOECHO)sed "s/%ROMBASE%/$(ROMBASE)/;s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
@@ -0,0 +1,83 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = %MEMBASE%;
/* text/read-only data */
.text.boot : { *(.text.boot) }
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x9090
.plt : { *(.plt) }
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(4);
__commands_start = .;
KEEP (*(.commands))
__commands_end = .;
. = ALIGN(4);
__apps_start = .;
KEEP (*(.apps))
__apps_end = .;
. = ALIGN(4);
__rodata_end = . ;
}
/* writable data */
__data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */
__data_start = .;
.data : SUBALIGN(4) { *(.data .data.* .gnu.linkonce.d.*) }
__ctor_list = .;
.ctors : { *(.ctors) }
__ctor_end = .;
__dtor_list = .;
.dtors : { *(.dtors) }
__dtor_end = .;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
__data_end = .;
/* unintialized data (in same segment as writable data) */
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss .bss.*) }
. = ALIGN(4);
_end = .;
. = %MEMBASE% + %MEMSIZE%;
_end_of_ram = .;
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note .eh_frame) }
}
@@ -0,0 +1,86 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = %ROMBASE%;
/* text/read-only data */
.text.boot : { *(.text.boot) }
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x9090
.plt : { *(.plt) }
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(4);
__commands_start = .;
KEEP (*(.commands))
__commands_end = .;
. = ALIGN(4);
__apps_start = .;
KEEP (*(.apps))
__apps_end = .;
. = ALIGN(4);
__rodata_end = . ;
}
/* writable data */
__data_start_rom = .;
. = %MEMBASE%;
__data_start = .;
.data :
AT ( ADDR (.rodata) + SIZEOF (.rodata) )
{ *(.data .data.* .gnu.linkonce.d.*) }
__ctor_list = .;
.ctors : { *(.ctors) }
__ctor_end = .;
__dtor_list = .;
.dtors : { *(.dtors) }
__dtor_end = .;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
__data_end = .;
/* unintialized data (in same segment as writable data) */
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss .bss.*) }
. = ALIGN(4);
_end = . ;
. = %MEMBASE% + %MEMSIZE%;
_end_of_ram = . ;
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note .eh_frame) }
}
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <debug.h>
#include <kernel/thread.h>
#include <arch/arm.h>
struct context_switch_frame {
vaddr_t r4;
vaddr_t r5;
vaddr_t r6;
vaddr_t r7;
vaddr_t r8;
vaddr_t r9;
vaddr_t r10;
vaddr_t r11;
vaddr_t lr;
vaddr_t usp;
vaddr_t ulr;
};
extern void arm_context_switch(addr_t *old_sp, addr_t new_sp);
static void initial_thread_func(void) __NO_RETURN;
static void initial_thread_func(void)
{
int ret;
// dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
// dump_thread(current_thread);
/* exit the implicit critical section we're within */
exit_critical_section();
ret = current_thread->entry(current_thread->arg);
// dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
thread_exit(ret);
}
void arch_thread_initialize(thread_t *t)
{
// create a default stack frame on the stack
vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
// make sure the top of the stack is 8 byte aligned for EABI compliance
stack_top = ROUNDDOWN(stack_top, 8);
struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
frame--;
// fill it in
memset(frame, 0, sizeof(*frame));
frame->lr = (vaddr_t)&initial_thread_func;
// set the stack pointer
t->arch.sp = (vaddr_t)frame;
}
void arch_context_switch(thread_t *oldthread, thread_t *newthread)
{
// dprintf("arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
arm_context_switch(&oldthread->arch.sp, newthread->arch.sp);
}
@@ -0,0 +1,92 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
/*Added TRUSTZONE at 0x0. Moving rest of APPSBL to %MEMBASE% */
. = 0x0;
.tzbsp 0x0 : {*tzbsp_bin.o(.data)}
. = %MEMBASE%;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
/*Moving harcoded addresses by a displacement of %MEMBASE% */
.init : { *(.init) } = %MEMBASE% + 0x9090
.plt : { *(.plt) }
/* text/read-only data */
/*Moving harcoded addresses by a displacement of %MEMBASE% */
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } = %MEMBASE% + 0x9090
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(4);
__commands_start = .;
KEEP (*(.commands))
__commands_end = .;
. = ALIGN(4);
__apps_start = .;
KEEP (*(.apps))
__apps_end = .;
. = ALIGN(4);
__rodata_end = . ;
}
/* writable data */
__data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */
__data_start = .;
.data : SUBALIGN(4) { *(.data .data.* .gnu.linkonce.d.*) }
__ctor_list = .;
.ctors : { *(.ctors) }
__ctor_end = .;
__dtor_list = .;
.dtors : { *(.dtors) }
__dtor_end = .;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
__data_end = .;
/* unintialized data (in same segment as writable data) */
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss .bss.*) }
. = ALIGN(4);
_end = .;
. = %MEMBASE% + %MEMSIZE%;
_end_of_ram = .;
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note .eh_frame) }
}
@@ -0,0 +1,93 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
/*Added TRUSTZONE at 0x0. Moving rest of APPSBL to %MEMBASE% */
. = 0x0;
.tzbsp 0x0 : {*tzbsp_bin.o(.data)}
.romlite 0xBF000 : {*romlite_toc_and_data.o(.data.rom_lite_preflashed_data)}
. = %MEMBASE%;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
/*Moving harcoded addresses by a displacement of %MEMBASE% */
.init : { *(.init) } = %MEMBASE% + 0x9090
.plt : { *(.plt) }
/* text/read-only data */
/*Moving harcoded addresses by a displacement of %MEMBASE% */
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } = %MEMBASE% + 0x9090
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(4);
__commands_start = .;
KEEP (*(.commands))
__commands_end = .;
. = ALIGN(4);
__apps_start = .;
KEEP (*(.apps))
__apps_end = .;
. = ALIGN(4);
__rodata_end = . ;
}
/* writable data */
__data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */
__data_start = .;
.data : SUBALIGN(4) { *(.data .data.* .gnu.linkonce.d.*) }
__ctor_list = .;
.ctors : { *(.ctors) }
__ctor_end = .;
__dtor_list = .;
.dtors : { *(.dtors) }
__dtor_end = .;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
__data_end = .;
/* unintialized data (in same segment as writable data) */
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss .bss.*) }
. = ALIGN(4);
_end = .;
. = %MEMBASE% + %MEMSIZE%;
_end_of_ram = .;
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note .eh_frame) }
}
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <arch.h>
#include <arch/ops.h>
#include <arch/x86.h>
#include <arch/x86/mmu.h>
#include <arch/x86/descriptor.h>
#include <platform.h>
#include <sys/types.h>
#include <string.h>
static tss_t system_tss;
void arch_early_init(void)
{
x86_mmu_init();
platform_init_mmu_mappings();
/* enable caches here for now */
clear_in_cr0(X86_CR0_NW | X86_CR0_CD);
memset(&system_tss, 0, sizeof(tss_t));
system_tss.esp0 = 0;
system_tss.ss0 = DATA_SELECTOR;
system_tss.ss1 = 0;
system_tss.ss2 = 0;
system_tss.eflags = 0x00003002;
system_tss.bitmap = offsetof(tss_t, tss_bitmap);
system_tss.trace = 1; // trap on hardware task switch
set_global_desc(TSS_SELECTOR, &system_tss, sizeof(tss_t), 1, 0, 0, SEG_TYPE_TSS, 0, 0);
x86_ltr(TSS_SELECTOR);
}
void arch_init(void)
{
}
uint32_t arch_cycle_count(void)
{
uint32_t timestamp;
rdtscl(timestamp);
return timestamp;
}
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/ops.h>
#include <arch/defines.h>
.text
/* stubs */
FUNCTION(arch_disable_cache)
ret
FUNCTION(arch_enable_cache)
ret
FUNCTION(arch_clean_cache_range)
ret
FUNCTION(arch_clean_invalidate_cache_range)
ret
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
@@ -0,0 +1,16 @@
$(BUILDDIR)/%.o: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+315
View File
@@ -0,0 +1,315 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* The magic number for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* The flags for the Multiboot header. */
#if defined(__ELF__) && 0
#define MULTIBOOT_HEADER_FLAGS 0x00000002
#else
#define MULTIBOOT_HEADER_FLAGS 0x00010002
#endif
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
#define NUM_INT 0x31
#define NUM_EXC 0x14
.text
.global _start
_start:
jmp real_start
.align 4
multiboot_header:
/* magic */
.int MULTIBOOT_HEADER_MAGIC
/* flags */
.int MULTIBOOT_HEADER_FLAGS
/* checksum */
.int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
#if !defined(__ELF__) || 1
/* header_addr */
.int multiboot_header
/* load_addr */
.int _start
/* load_end_addr */
.int __bss_start
/* bss_end_addr */
.int __bss_end
/* entry_addr */
.int real_start
#endif
real_start:
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
jne 0f
movl %ebx, (_multiboot_info)
0:
/* setup isr stub descriptors in the idt */
movl $_isr, %esi
movl $_idt, %edi
movl $NUM_INT, %ecx
.Lloop:
movl %esi, %ebx
movw %bx, (%edi) /* low word in IDT(n).low */
shrl $16, %ebx
movw %bx, 6(%edi) /* high word in IDT(n).high */
addl $isr_stub_len, %esi/* index the next ISR stub */
addl $8, %edi /* index the next IDT entry */
loop .Lloop
lidt _idtr
xorl %eax, %eax
movl %eax, %cr3
lgdt _gdtr
movw $datasel, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %ss
movw %ax, %gs
movw %ax, %ss
movl $_kstack, %esp
/* zero the bss section */
movl $__bss_start, %edi /* starting address of the bss */
movl $__bss_end, %ecx /* find the length of the bss in bytes */
subl %edi, %ecx
shrl $2, %ecx /* convert to 32 bit words, since the bss is aligned anyway */
2:
movl $0, (%edi)
addl $4, %edi
loop 2b
/* call the main module */
call kmain
0: /* just sit around waiting for interrupts */
hlt /* interrupts will unhalt the processor */
pause
jmp 0b /* so jump back to halt to conserve power */
/* interrupt service routine stubs */
_isr:
.set i, 0
.rept NUM_INT
.set isr_stub_start, .
.if i == 8 || (i >= 10 && i <= 14) || i == 17
nop /* error code pushed by exception */
nop /* 2 nops are the same length as push byte */
pushl $i /* interrupt number */
jmp interrupt_common
.else
pushl $0 /* fill in error code in iframe */
pushl $i /* interrupt number */
jmp interrupt_common
.endif
/* figure out the length of a single isr stub (usually 6 or 9 bytes) */
.set isr_stub_len, . - isr_stub_start
.set i, i + 1
.endr
/* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */
.fill 256
interrupt_common:
pushl %gs /* save segment registers */
pushl %fs
pushl %es
pushl %ds
pusha /* save general purpose registers */
movl $datasel, %eax /* put known good value in segment registers */
movl %eax, %gs
movl %eax, %fs
movl %eax, %es
movl %eax, %ds
movl %esp, %eax /* store stack switch pivot. push esp has errata on some cpus, so use mov/push */
pushl %eax
movl %esp, %eax /* store pointer to iframe, using same method */
pushl %eax
incl critical_section_count
call platform_irq
cmpl $0,%eax
je 0f
call thread_preempt
0:
decl critical_section_count
popl %eax /* drop pointer to iframe */
popl %eax /* restore task_esp, stack switch can occur here if task_esp is modified */
movl %eax, %esp
popa /* restore general purpose registers */
popl %ds /* restore segment registers */
popl %es
popl %fs
popl %gs
addl $8, %esp /* drop exception number and error code */
iret
.data
.align 4
/* define the heap end as read-write data containing the default end of the
* heap. dynamic memory length discovery can update this value during init.
* other archs can define this statically based on the memory layout of the
* platform.
*/
.global _heap_end
_heap_end:
.int 4096*1024 /* default to 4MB total */
.global _multiboot_info
_multiboot_info:
.int 0
.global _gdtr
_gdtr:
.short _gdt_end - _gdt - 1
.int _gdt
.global _gdt
_gdt:
.int 0
.int 0
/* ring 0 descriptors */
.set codesel, . - _gdt
_code_gde:
.short 0xffff /* limit 15:00 */
.short 0x0000 /* base 15:00 */
.byte 0x00 /* base 23:16 */
.byte 0b10011010 /* P(1) DPL(00) S(1) 1 C(0) R(1) A(0) */
.byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
.byte 0x0 /* base 31:24 */
.set datasel, . - _gdt
_data_gde:
.short 0xffff /* limit 15:00 */
.short 0x0000 /* base 15:00 */
.byte 0x00 /* base 23:16 */
.byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
.byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
.byte 0x0 /* base 31:24 */
.set videosel, . - _gdt
_video_gde:
.short 0xffff /* limit 15:00 */
.short 0x8000 /* base 15:00 */
.byte 0x0b /* base 23:16 */
.byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
.byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
.byte 0x0 /* base 31:24 */
.if 1
/* ring 3 descriptors */
.set user_codesel, . - _gdt
_user_code_gde:
.short 0xffff /* limit 15:00 */
.short 0x0000 /* base 15:00 */
.byte 0x00 /* base 23:16 */
.byte 0b11111010 /* P(1) DPL(11) S(1) 1 C(0) R(1) A(0) */
.byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
.byte 0x0 /* base 31:24 */
.set user_datasel, . - _gdt
_user_data_gde:
.short 0xffff /* limit 15:00 */
.short 0x0000 /* base 15:00 */
.byte 0x00 /* base 23:16 */
.byte 0b11110010 /* P(1) DPL(11) S(1) 0 E(0) W(1) A(0) */
.byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
.byte 0x0 /* base 31:24 */
.endif
/* TSS descriptor */
.if 1
.set tsssel, . - _gdt
_tss_gde:
.short 0 /* limit 15:00 */
.short 0 /* base 15:00 */
.byte 0 /* base 23:16 */
.byte 0xe9 /* P(1) DPL(11) 0 10 B(0) 1 */
.byte 0x00 /* G(0) 0 0 AVL(0) limit 19:16 */
.short 0 /* base 31:24 */
.endif
.global _gdt_end
_gdt_end:
.global _idtr
_idtr:
.short _idt_end - _idt - 1 /* IDT limit */
.int _idt
/* interrupt descriptor table (IDT) */
.global _idt
_idt:
.set i, 0
.rept NUM_INT-1
.short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
.short codesel /* selector */
.byte 0
.byte 0x8e /* present, ring 0, 32-bit interrupt gate */
.short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
.set i, i + 1
.endr
/* syscall int (ring 3) */
_idt30:
.short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
.short codesel /* selector */
.byte 0
.byte 0xee /* present, ring 3, 32-bit interrupt gate */
.short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
.global _idt_end
_idt_end:
.bss
.align 4096
.global _kstack
.fill 4096
_kstack:
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <compiler.h>
#include <arch/x86/descriptor.h>
/* not the best way to do this, but easy for now */
typedef struct {
uint16_t limit_15_0;
uint16_t base_15_0;
uint8_t base_23_16;
uint8_t type : 4;
uint8_t s : 1;
uint8_t dpl : 2;
uint8_t p : 1;
uint8_t limit_19_16 : 4;
uint8_t avl : 1;
uint8_t reserved_0 : 1;
uint8_t d_b : 1;
uint8_t g : 1;
uint8_t base_31_24;
} __PACKED seg_desc_t;
extern seg_desc_t _gdt[];
void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits)
{
// convert selector into index
uint16_t index = sel >> 3;
_gdt[index].limit_15_0 = limit & 0x0000ffff;
_gdt[index].limit_19_16 = (limit & 0x000f0000) >> 16;
_gdt[index].base_15_0 = ((uint32_t) base) & 0x0000ffff;
_gdt[index].base_23_16 = (((uint32_t) base) & 0x00ff0000) >> 16;
_gdt[index].base_31_24 = ((uint32_t) base) >> 24;
_gdt[index].type = type & 0x0f; // segment type
_gdt[index].p = present != 0; // present
_gdt[index].dpl = ring & 0x03; // descriptor privilege level
_gdt[index].g = gran != 0; // granularity
_gdt[index].s = sys != 0; // system / non-system
_gdt[index].d_b = bits != 0; // 16 / 32 bit
}
+77
View File
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <arch/x86.h>
#include <kernel/thread.h>
static void dump_fault_frame(struct x86_iframe *frame)
{
dprintf(CRITICAL, " CS: %04x EIP: %08x EFL: %08x CR2: %08x\n",
frame->cs, frame->eip, frame->eflags, x86_get_cr2());
dprintf(CRITICAL, "EAX: %08x ECX: %08x EDX: %08x EBX: %08x\n",
frame->eax, frame->ecx, frame->edx, frame->ebx);
dprintf(CRITICAL, "ESP: %08x EBP: %08x ESI: %08x EDI: %08x\n",
frame->esp, frame->ebp, frame->esi, frame->edi);
dprintf(CRITICAL, " DS: %04x ES: %04x FS: %04x GS: %04x\n",
frame->ds, frame->es, frame->fs, frame->gs);
// dump the bottom of the current stack
addr_t stack = (addr_t) frame; //(addr_t) (((uint32_t *) frame) + (sizeof(struct x86_iframe) / sizeof(uint32_t) - 1));
if (stack != 0) {
dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
hexdump((void *)stack, 192);
}
}
static void exception_die(struct x86_iframe *frame, const char *msg)
{
inc_critical_section();
dprintf(CRITICAL, msg);
dump_fault_frame(frame);
for (;;) {
x86_cli();
x86_hlt();
}
}
void x86_syscall_handler(struct x86_iframe *frame)
{
exception_die(frame, "unhandled syscall, halting\n");
}
void x86_gpf_handler(struct x86_iframe *frame)
{
exception_die(frame, "unhandled gpf, halting\n");
}
void x86_invop_handler(struct x86_iframe *frame)
{
exception_die(frame, "unhandled invalid op, halting\n");
}
void x86_unhandled_exception(struct x86_iframe *frame)
{
exception_die(frame, "unhandled exception, halting\n");
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __X86_ARCH_THREAD_H
#define __X86_ARCH_THREAD_H
struct arch_thread {
vaddr_t esp;
// TODO: fpu context
};
#endif
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_CPU_H
#define __ARCH_CPU_H
#define PAGE_SIZE 4096
// TODO: define to resolve to platform setup discovered value
#define CACHE_LINE 32
#endif
@@ -0,0 +1,264 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_X86_H
#define __ARCH_X86_H
#include <compiler.h>
#include <sys/types.h>
#if defined(__cplusplus)
extern "C" {
#endif
void x86_mmu_init(void);
struct x86_iframe {
uint32_t pivot; // stack switch pivot
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // pushed by common handler using pusha
uint32_t ds, es, fs, gs; // pushed by common handler
uint32_t vector; // pushed by stub
uint32_t err_code; // pushed by interrupt or stub
uint32_t eip, cs, eflags; // pushed by interrupt
uint32_t user_esp, user_ss; // pushed by interrupt if priv change occurs
};
/*
* x86 TSS structure
*/
typedef struct {
uint16_t backlink, __blh;
uint32_t esp0;
uint16_t ss0, __ss0h;
uint32_t esp1;
uint16_t ss1, __ss1h;
uint32_t esp2;
uint16_t ss2, __ss2h;
uint32_t cr3;
uint32_t eip;
uint32_t eflags;
uint32_t eax, ecx, edx, ebx;
uint32_t esp, ebp, esi, edi;
uint16_t es, __esh;
uint16_t cs, __csh;
uint16_t ss, __ssh;
uint16_t ds, __dsh;
uint16_t fs, __fsh;
uint16_t gs, __gsh;
uint16_t ldt, __ldth;
uint16_t trace, bitmap;
uint8_t tss_bitmap[8192];
} __PACKED tss_t;
#define X86_CR0_PE 0x00000001 /* protected mode enable */
#define X86_CR0_MP 0x00000002 /* monitor coprocessor */
#define X86_CR0_EM 0x00000004 /* emulation */
#define X86_CR0_TS 0x00000008 /* task switched */
#define X86_CR0_WP 0x00010000 /* supervisor write protect */
#define X86_CR0_NW 0x20000000 /* not write-through */
#define X86_CR0_CD 0x40000000 /* cache disable */
#define X86_CR0_PG 0x80000000 /* enable paging */
static inline void set_in_cr0(uint32_t mask) {
__asm__ __volatile__ (
"movl %%cr0,%%eax \n\t"
"orl %0,%%eax \n\t"
"movl %%eax,%%cr0 \n\t"
: : "irg" (mask)
:"ax");
}
static inline void clear_in_cr0(uint32_t mask) {
__asm__ __volatile__ (
"movl %%cr0, %%eax \n\t"
"andl %0, %%eax \n\t"
"movl %%eax, %%cr0 \n\t"
: : "irg" (~mask)
: "ax");
}
static inline void x86_clts(void) {__asm__ __volatile__ ("clts"); }
static inline void x86_hlt(void) {__asm__ __volatile__ ("hlt"); }
static inline void x86_sti(void) {__asm__ __volatile__ ("sti"); }
static inline void x86_cli(void) {__asm__ __volatile__ ("cli"); }
static inline void x86_ltr(uint16_t sel) {
__asm__ __volatile__ ("ltr %%ax" :: "a" (sel));
}
static inline uint32_t x86_get_cr2(void) {
uint32_t rv;
__asm__ __volatile__ (
"movl %%cr2, %0"
: "=r" (rv)
);
return rv;
}
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
#define rdtscl(low) \
__asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
#define rdtscll(val) \
__asm__ __volatile__("rdtsc" : "=A" (val))
static inline uint8_t inp(uint16_t _port) {
uint8_t rv;
__asm__ __volatile__ ("inb %1, %0"
: "=a" (rv)
: "d" (_port));
return(rv);
}
static inline uint16_t inpw (uint16_t _port) {
uint16_t rv;
__asm__ __volatile__ ("inw %1, %0"
: "=a" (rv)
: "d" (_port));
return(rv);
}
static inline uint32_t inpd(uint16_t _port) {
uint32_t rv;
__asm__ __volatile__ ("inl %1, %0"
: "=a" (rv)
: "d" (_port));
return(rv);
}
static inline void outp(uint16_t _port, uint8_t _data) {
__asm__ __volatile__ ("outb %1, %0"
:
: "d" (_port),
"a" (_data));
}
static inline void outpw(uint16_t _port, uint16_t _data) {
__asm__ __volatile__ ("outw %1, %0"
:
: "d" (_port),
"a" (_data));
}
static inline void outpd(uint16_t _port, uint32_t _data) {
__asm__ __volatile__ ("outl %1, %0"
:
: "d" (_port),
"a" (_data));
}
static inline void inprep(uint16_t _port, uint8_t *_buffer, uint32_t _reads) {
__asm__ __volatile__ ("pushal \n\t"
"pushfl \n\t"
"cli \n\t"
"cld \n\t"
"rep insb \n\t"
"popfl \n\t"
"popal"
:
: "d" (_port),
"D" (_buffer),
"c" (_reads));
}
static inline void outprep(uint16_t _port, uint8_t *_buffer, uint32_t _writes) {
__asm__ __volatile__ ("pushal \n\t"
"pushfl \n\t"
"cli \n\t"
"cld \n\t"
"rep outsb \n\t"
"popfl \n\t"
"popal"
:
: "d" (_port),
"S" (_buffer),
"c" (_writes));
}
static inline void inpwrep(uint16_t _port, uint16_t *_buffer, uint32_t _reads) {
__asm__ __volatile__ ("pushal \n\t"
"pushfl \n\t"
"cli \n\t"
"cld \n\t"
"rep insw \n\t"
"popfl \n\t"
"popal"
:
: "d" (_port),
"D" (_buffer),
"c" (_reads));
}
static inline void outpwrep(uint16_t _port, uint16_t *_buffer,
uint32_t _writes) {
__asm__ __volatile__ ("pushal \n\t"
"pushfl \n\t"
"cli \n\t"
"cld \n\t"
"rep outsw \n\t"
"popfl \n\t"
"popal"
:
: "d" (_port),
"S" (_buffer),
"c" (_writes));
}
static inline void inpdrep(uint16_t _port, uint32_t *_buffer,
uint32_t _reads) {
__asm__ __volatile__ ("pushal \n\t"
"pushfl \n\t"
"cli \n\t"
"cld \n\t"
"rep insl \n\t"
"popfl \n\t"
"popal"
:
: "d" (_port),
"D" (_buffer),
"c" (_reads));
}
static inline void outpdrep(uint16_t _port, uint32_t *_buffer,
uint32_t _writes) {
__asm__ __volatile__ ("pushal \n\t"
"pushfl \n\t"
"cli \n\t"
"cld \n\t"
"rep outsl \n\t"
"popfl \n\t"
"popal"
:
: "d" (_port),
"S" (_buffer),
"c" (_writes));
}
#if defined(__cplusplus)
}
#endif
#endif
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_DESCRIPTOR_H
#define __ARCH_DESCRIPTOR_H
#include <sys/types.h>
/*
* System Selectors
*/
#define CODE_SELECTOR 0x08
#define DATA_SELECTOR 0x10
#define VIDEO_SELECTOR 0x18
#define TSS_SELECTOR 0x30
#define USER_CODE_SELECTOR 0x23
#define USER_DATA_SELECTOR 0x2b
/*
* Descriptor Types
*/
#define SEG_TYPE_TSS 0x9
#define SEG_TYPE_TSS_BUSY 0xb
#define SEG_TYPE_TASK_GATE 0x5
#define SEG_TYPE_INT_GATE 0xe // 32 bit
#define SEG_TYPE_DATA_RW 0x2
#define SEG_TYPE_CODE_RW 0xa
typedef uint16_t seg_sel_t;
void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits);
#endif
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_MMU_H
#define __ARCH_ARM_MMU_H
#include <sys/types.h>
#if defined(__cplusplus)
extern "C" {
#endif
void arm_mmu_init(void);
#define MMU_FLAG_CACHED 0x1
#define MMU_FLAG_BUFFERED 0x2
#define MMU_FLAG_READWRITE 0x4
void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags);
#if defined(__cplusplus)
}
#endif
#endif
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_X86_OPS_H
#define __ARHC_X86_OPS_H
#if 0
#include <compiler.h>
#ifndef ASSEMBLY
// override of some routines
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
{
__asm__ __volatile__ ("sti");
}
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
{
__asm__ __volatile__ ("cli");
}
#endif
#endif
#endif
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
ENTRY(_start)
SECTIONS
{
.text 0x0200000 : {
*(.text)
*(SORT(.text$*))
*(.gnu.linkonce.t.*)
__ctor_list = .;
*(SORT(.ctor*))
__ctor_end = .;
__dtor_list = .;
*(SORT(.dtor*))
__dtor_end = .;
. = ALIGN(4096);
}
__data_start = .;
.data : { *(.data .data.* .gnu.linkonce.d.*) }
.stab : { *(.stab) }
.stabst : { *(.stabstr) }
. = ALIGN(4096);
__data_end = .;
.rdata : {
*(.rdata)
*(SORT(.rdata$*))
*(.rodata*)
*(.gnu.linkonce.r.*)
__commands_start = .;
KEEP (*(.commands))
__commands_end = .;
. = ALIGN(4);
__apps_start = .;
KEEP (*(.apps))
__apps_end = .;
. = ALIGN(4096);
}
__bss_start = .;
.bss : {
*(.bss*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4096);
}
__bss_end = .;
/*. += 0x2000;
_kstack = .;
. += 0x1000;*/
_end = .;
/DISCARD/ : { *(.comment .note .eh_frame) }
}
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <sys/types.h>
#include <compiler.h>
#include <arch.h>
#include <arch/x86.h>
#include <arch/x86/mmu.h>
void x86_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags)
{
// TODO: stuff
//x86_invalidate_tlb();
}
void x86_mmu_init(void)
{
// TODO: stuff
}
void arch_disable_mmu(void)
{
// TODO: stuff
}
+97
View File
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
.text
/* void arch_enable_ints(void); */
FUNCTION(arch_enable_ints)
sti
ret
/* void arch_disable_ints(void); */
FUNCTION(arch_disable_ints)
cli
ret
/* int atomic_swap(int *ptr, int val); */
FUNCTION(atomic_swap)
movl 4(%esp), %edx
movl 8(%esp), %eax
xchgl %eax, (%edx)
ret
/* int atomic_add(int *ptr, int val); */
FUNCTION(atomic_add)
movl 4(%esp), %edx
movl 8(%esp), %eax
lock
xadd %eax, (%edx)
ret
/* int atomic_and(int *ptr, int val); */
FUNCTION(atomic_and)
movl 4(%esp), %edx
movl (%edx), %eax
0:
movl %eax, %ecx
andl 8(%esp), %ecx
lock
cmpxchgl %ecx, (%edx)
jnz 1f /* static prediction: branch forward not taken */
ret
1:
jmp 0b
/* int atomic_or(int *ptr, int val); */
FUNCTION(atomic_or)
movl 4(%esp), %edx
movl (%edx), %eax
0:
movl %eax, %ecx
orl 8(%esp), %ecx
lock
cmpxchgl %ecx, (%edx)
jnz 1f /* static prediction: branch forward not taken */
ret
1:
jmp 0b
/* void arch_idle(); */
FUNCTION(arch_idle)
pushf
popl %eax
andl $0x200, %eax
test %eax, %eax
je 1f /* don't halt if local interrupts are disabled */
hlt
1:
ret
/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
FUNCTION(arch_switch_stacks_and_call)
movl 4(%esp), %eax
movl 8(%esp), %edx
movl %edx, %esp
call *%eax /* perhaps this should be a jmp? it's not used anywhere so I don't know. */
+41
View File
@@ -0,0 +1,41 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
INCLUDES += \
-I$(LOCAL_DIR)/include
BOOTOBJS += \
$(LOCAL_DIR)/crt0.o
OBJS += \
$(LOCAL_DIR)/arch.o \
$(LOCAL_DIR)/asm.o \
$(LOCAL_DIR)/cache.o \
$(LOCAL_DIR)/cache-ops.o \
$(LOCAL_DIR)/ops.o \
$(LOCAL_DIR)/thread.o \
$(LOCAL_DIR)/mmu.o \
$(LOCAL_DIR)/faults.o \
$(LOCAL_DIR)/descriptor.o
# set the default toolchain to x86 elf and set a #define
TOOLCHAIN_PREFIX ?= i386-elf-
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) -print-libgcc-file-name)
#$(info LIBGCC = $(LIBGCC))
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`"; \
then echo "$(2)"; else echo "$(3)"; fi ;)
# disable SSP if the compiler supports it; it will break stuff
CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
# potentially generated files that should be cleaned out with clean make rule
GENERATED += \
$(BUILDDIR)/kernel.ld
# rules for generating the linker scripts
$(BUILDDIR)/kernel.ld: $(LOCAL_DIR)/kernel.ld
@echo generating $@
@$(MKDIR)
$(NOECHO)cp $< $@
+129
View File
@@ -0,0 +1,129 @@
/*
* Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <debug.h>
#include <kernel/thread.h>
#include <arch/x86.h>
#include <arch/x86/descriptor.h>
/*struct context_switch_frame {
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t ds, es, fs, gs;
uint32_t eip, cs, eflags;
};*/
struct context_switch_frame {
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t eflags;
uint32_t eip;
};
extern void x86_context_switch(addr_t *old_sp, addr_t new_sp);
static void initial_thread_func(void) __NO_RETURN;
static void initial_thread_func(void)
{
int ret;
// dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
// dump_thread(current_thread);
/* exit the implicit critical section we're within */
exit_critical_section();
ret = current_thread->entry(current_thread->arg);
// dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
thread_exit(ret);
}
void arch_thread_initialize(thread_t *t)
{
// create a default stack frame on the stack
vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
// make sure the top of the stack is 8 byte aligned for EABI compliance
stack_top = ROUNDDOWN(stack_top, 8);
struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
frame--;
// fill it in
memset(frame, 0, sizeof(*frame));
frame->eip = (vaddr_t) &initial_thread_func;
frame->eflags = 0x3002; // IF = 0, NT = 0, IOPL = 3
//frame->cs = CODE_SELECTOR;
//frame->fs = DATA_SELECTOR;
//frame->gs = DATA_SELECTOR;
//frame->es = DATA_SELECTOR;
//frame->ds = DATA_SELECTOR;
// set the stack pointer
t->arch.esp = (vaddr_t)frame;
}
void arch_context_switch(thread_t *oldthread, thread_t *newthread)
{
//dprintf(DEBUG, "arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
__asm__ __volatile__ (
"pushl $1f \n\t"
"pushf \n\t"
"pusha \n\t"
"movl %%esp,(%%edx) \n\t"
"movl %%eax,%%esp \n\t"
"popa \n\t"
"popf \n\t"
"ret \n\t"
"1: \n\t"
:
: "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
);
/*__asm__ __volatile__ (
"pushf \n\t"
"pushl %%cs \n\t"
"pushl $1f \n\t"
"pushl %%gs \n\t"
"pushl %%fs \n\t"
"pushl %%es \n\t"
"pushl %%ds \n\t"
"pusha \n\t"
"movl %%esp,(%%edx) \n\t"
"movl %%eax,%%esp \n\t"
"popa \n\t"
"popl %%ds \n\t"
"popl %%es \n\t"
"popl %%fs \n\t"
"popl %%gs \n\t"
"iret \n\t"
"1: "
:
: "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
);*/
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
void dev_init(void)
{
}
+260
View File
@@ -0,0 +1,260 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Copyright (c) 2009-2011, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <debug.h>
#include <err.h>
#include <stdlib.h>
#include <dev/fbcon.h>
#include <splash.h>
#include <platform.h>
#include <string.h>
#include "font5x12.h"
struct pos {
int x;
int y;
};
static struct fbcon_config *config = NULL;
#define RGB565_BLACK 0x0000
#define RGB565_WHITE 0xffff
#define RGB888_BLACK 0x000000
#define RGB888_WHITE 0xffffff
#define FONT_WIDTH 5
#define FONT_HEIGHT 12
static uint16_t BGCOLOR;
static uint16_t FGCOLOR;
static struct pos cur_pos;
static struct pos max_pos;
static void fbcon_drawglyph(uint16_t *pixels, uint16_t paint, unsigned stride,
unsigned *glyph)
{
unsigned x, y, data;
stride -= FONT_WIDTH;
data = glyph[0];
for (y = 0; y < (FONT_HEIGHT / 2); ++y) {
for (x = 0; x < FONT_WIDTH; ++x) {
if (data & 1)
*pixels = paint;
data >>= 1;
pixels++;
}
pixels += stride;
}
data = glyph[1];
for (y = 0; y < (FONT_HEIGHT / 2); y++) {
for (x = 0; x < FONT_WIDTH; x++) {
if (data & 1)
*pixels = paint;
data >>= 1;
pixels++;
}
pixels += stride;
}
}
static void fbcon_flush(void)
{
if (config->update_start)
config->update_start();
if (config->update_done)
while (!config->update_done());
}
/* TODO: Take stride into account */
static void fbcon_scroll_up(void)
{
unsigned short *dst = config->base;
unsigned short *src = dst + (config->width * FONT_HEIGHT);
unsigned count = config->width * (config->height - FONT_HEIGHT);
while(count--) {
*dst++ = *src++;
}
count = config->width * FONT_HEIGHT;
while(count--) {
*dst++ = BGCOLOR;
}
fbcon_flush();
}
/* TODO: take stride into account */
void fbcon_clear(void)
{
unsigned count = config->width * config->height;
memset(config->base, BGCOLOR, count * ((config->bpp) / 8));
}
static void fbcon_set_colors(unsigned bg, unsigned fg)
{
BGCOLOR = bg;
FGCOLOR = fg;
}
void fbcon_putc(char c)
{
uint16_t *pixels;
/* ignore anything that happens before fbcon is initialized */
if (!config)
return;
if((unsigned char)c > 127)
return;
if((unsigned char)c < 32) {
if(c == '\n')
goto newline;
else if (c == '\r')
cur_pos.x = 0;
return;
}
pixels = config->base;
pixels += cur_pos.y * FONT_HEIGHT * config->width;
pixels += cur_pos.x * (FONT_WIDTH + 1);
fbcon_drawglyph(pixels, FGCOLOR, config->stride,
font5x12 + (c - 32) * 2);
cur_pos.x++;
if (cur_pos.x < max_pos.x)
return;
newline:
cur_pos.y++;
cur_pos.x = 0;
if(cur_pos.y >= max_pos.y) {
cur_pos.y = max_pos.y - 1;
fbcon_scroll_up();
} else
fbcon_flush();
}
void fbcon_setup(struct fbcon_config *_config)
{
uint32_t bg;
uint32_t fg;
ASSERT(_config);
config = _config;
switch (config->format) {
case FB_FORMAT_RGB565:
fg = RGB565_WHITE;
bg = RGB565_BLACK;
break;
case FB_FORMAT_RGB888:
fg = RGB888_WHITE;
bg = RGB888_BLACK;
break;
default:
dprintf(CRITICAL, "unknown framebuffer pixel format\n");
ASSERT(0);
break;
}
fbcon_set_colors(bg, fg);
cur_pos.x = 0;
cur_pos.y = 0;
max_pos.x = config->width / (FONT_WIDTH+1);
max_pos.y = (config->height - 1) / FONT_HEIGHT;
#if !DISPLAY_SPLASH_SCREEN
fbcon_clear();
#endif
}
struct fbcon_config* fbcon_display(void)
{
return config;
}
void display_image_on_screen(void)
{
unsigned i = 0;
unsigned total_x;
unsigned total_y;
unsigned bytes_per_bpp;
unsigned image_base;
if (!config) {
dprintf(CRITICAL,"NULL configuration, image cannot be displayed\n");
return;
}
fbcon_clear();
total_x = config->width;
total_y = config->height;
bytes_per_bpp = ((config->bpp) / 8);
image_base = ((((total_y/2) - (SPLASH_IMAGE_WIDTH / 2) - 1) *
(config->width)) + (total_x/2 - (SPLASH_IMAGE_HEIGHT / 2)));
#if DISPLAY_TYPE_MIPI
if (bytes_per_bpp == 3)
{
for (i = 0; i < SPLASH_IMAGE_WIDTH; i++)
{
memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
imageBuffer_rgb888 + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp),
SPLASH_IMAGE_HEIGHT * bytes_per_bpp);
}
}
fbcon_flush();
#if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
if(is_cmd_mode_enabled())
mipi_dsi_cmd_mode_trigger();
#endif
#else
if (bytes_per_bpp == 2)
{
for (i = 0; i < SPLASH_IMAGE_WIDTH; i++)
{
memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
imageBuffer + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp),
SPLASH_IMAGE_HEIGHT * bytes_per_bpp);
}
}
fbcon_flush();
#endif
}
+126
View File
@@ -0,0 +1,126 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
unsigned font5x12[] = {
0x00000000, 0x00000000,
0x08421080, 0x00020084,
0x00052940, 0x00000000,
0x15f52800, 0x0000295f,
0x1c52f880, 0x00023e94,
0x08855640, 0x0004d542,
0x04528800, 0x000b2725,
0x00021080, 0x00000000,
0x04211088, 0x00821042,
0x10841082, 0x00221108,
0x09575480, 0x00000000,
0x3e420000, 0x00000084,
0x00000000, 0x00223000,
0x3e000000, 0x00000000,
0x00000000, 0x00471000,
0x08844200, 0x00008442,
0x2318a880, 0x00022a31,
0x08429880, 0x000f9084,
0x1108c5c0, 0x000f8444,
0x1c4443e0, 0x00074610,
0x14a62100, 0x000423e9,
0x26d087e0, 0x00074610,
0x1e10c5c0, 0x00074631,
0x088443e0, 0x00010844,
0x1d18c5c0, 0x00074631,
0x3d18c5c0, 0x00074610,
0x08e20000, 0x00471000,
0x08e20000, 0x00223000,
0x02222200, 0x00082082,
0x01f00000, 0x000003e0,
0x20820820, 0x00008888,
0x1108c5c0, 0x00020084,
0x2b98c5c0, 0x000f05b5,
0x2318a880, 0x0008c63f,
0x1d2949e0, 0x0007ca52,
0x0210c5c0, 0x00074421,
0x252949e0, 0x0007ca52,
0x1e1087e0, 0x000f8421,
0x1e1087e0, 0x00008421,
0x0210c5c0, 0x00074639,
0x3f18c620, 0x0008c631,
0x084211c0, 0x00071084,
0x10842380, 0x00032508,
0x0654c620, 0x0008c525,
0x02108420, 0x000f8421,
0x2b5dc620, 0x0008c631,
0x2b59ce20, 0x0008c739,
0x2318c5c0, 0x00074631,
0x1f18c5e0, 0x00008421,
0x2318c5c0, 0x01075631,
0x1f18c5e0, 0x0008c525,
0x1c10c5c0, 0x00074610,
0x084213e0, 0x00021084,
0x2318c620, 0x00074631,
0x1518c620, 0x0002114a,
0x2b18c620, 0x000556b5,
0x08a54620, 0x0008c54a,
0x08a54620, 0x00021084,
0x088443e0, 0x000f8442,
0x0421084e, 0x00e10842,
0x08210420, 0x00084108,
0x1084210e, 0x00e42108,
0x0008a880, 0x00000000,
0x00000000, 0x01f00000,
0x00000104, 0x00000000,
0x20e00000, 0x000b663e,
0x22f08420, 0x0007c631,
0x22e00000, 0x00074421,
0x23e84200, 0x000f4631,
0x22e00000, 0x0007443f,
0x1e214980, 0x00010842,
0x22e00000, 0x1d187a31,
0x26d08420, 0x0008c631,
0x08601000, 0x00071084,
0x10c02000, 0x0c94a108,
0x0a908420, 0x0008a4a3,
0x084210c0, 0x00071084,
0x2ab00000, 0x0008d6b5,
0x26d00000, 0x0008c631,
0x22e00000, 0x00074631,
0x22f00000, 0x0210be31,
0x23e00000, 0x21087a31,
0x26d00000, 0x00008421,
0x22e00000, 0x00074506,
0x04f10800, 0x00064842,
0x23100000, 0x000b6631,
0x23100000, 0x00022951,
0x23100000, 0x000556b5,
0x15100000, 0x0008a884,
0x23100000, 0x1d185b31,
0x11f00000, 0x000f8444,
0x06421098, 0x01821084,
0x08421080, 0x00021084,
0x30421083, 0x00321084,
0x0004d640, 0x00000000,
0x00000000, 0x00000000,
};
@@ -0,0 +1,5 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/fbcon.o
@@ -0,0 +1,505 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <bits.h>
#include <stdlib.h>
#include <string.h>
#include <dev/keys.h>
#include <dev/gpio.h>
#include <dev/gpio_keypad.h>
#include <dev/ssbi.h>
#include <kernel/event.h>
#include <kernel/timer.h>
#include <reg.h>
#include <platform/iomap.h>
#include <platform/timer.h>
#include <platform.h>
#define LINUX_MACHTYPE_8660_QT 3298
struct gpio_kp {
struct gpio_keypad_info *keypad_info;
struct timer timer;
event_t full_scan;
int current_output;
unsigned int some_keys_pressed:2;
unsigned long keys_pressed[0];
};
struct gpio_qwerty_kp {
struct qwerty_keypad_info *keypad_info;
struct timer timer;
event_t full_scan;
unsigned int some_keys_pressed:2;
unsigned long keys_pressed[0];
};
static struct gpio_qwerty_kp *qwerty_keypad;
/* TODO: Support multiple keypads? */
static struct gpio_kp *keypad;
static void check_output(struct gpio_kp *kp, int out, int polarity)
{
struct gpio_keypad_info *kpinfo = kp->keypad_info;
int key_index;
int in;
int gpio;
int changed = 0;
key_index = out * kpinfo->ninputs;
for (in = 0; in < kpinfo->ninputs; in++, key_index++) {
gpio = kpinfo->input_gpios[in];
changed = 0;
if (gpio_get(gpio) ^ !polarity) {
if (kp->some_keys_pressed < 3)
kp->some_keys_pressed++;
changed = !bitmap_set(kp->keys_pressed, key_index);
} else {
changed = bitmap_clear(kp->keys_pressed, key_index);
}
if (changed) {
int state = bitmap_test(kp->keys_pressed, key_index);
keys_post_event(kpinfo->keymap[key_index], state);
}
}
/* sets up the right state for the next poll cycle */
gpio = kpinfo->output_gpios[out];
if (kpinfo->flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set(gpio, !polarity);
else
gpio_config(gpio, GPIO_INPUT);
}
static enum handler_return
gpio_keypad_timer_func(struct timer *timer, time_t now, void *arg)
{
struct gpio_kp *kp = keypad;
struct gpio_keypad_info *kpinfo = kp->keypad_info;
int polarity = !!(kpinfo->flags & GPIOKPF_ACTIVE_HIGH);
int out;
int gpio;
out = kp->current_output;
if (out == kpinfo->noutputs) {
out = 0;
kp->some_keys_pressed = 0;
} else {
check_output(kp, out, polarity);
out++;
}
kp->current_output = out;
if (out < kpinfo->noutputs) {
gpio = kpinfo->output_gpios[out];
if (kpinfo->flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set(gpio, polarity);
else
gpio_config(gpio, polarity ? GPIO_OUTPUT : 0);
timer_set_oneshot(timer, kpinfo->settle_time,
gpio_keypad_timer_func, NULL);
goto done;
}
if (/*!kp->use_irq*/ 1 || kp->some_keys_pressed) {
event_signal(&kp->full_scan, false);
timer_set_oneshot(timer, kpinfo->poll_time,
gpio_keypad_timer_func, NULL);
goto done;
}
done:
return INT_RESCHEDULE;
}
void gpio_keypad_init(struct gpio_keypad_info *kpinfo)
{
int key_count;
int output_val;
int output_cfg;
int i;
int len;
ASSERT(kpinfo->keymap && kpinfo->input_gpios && kpinfo->output_gpios);
key_count = kpinfo->ninputs * kpinfo->noutputs;
len = sizeof(struct gpio_kp) + (sizeof(unsigned long) *
BITMAP_NUM_WORDS(key_count));
keypad = malloc(len);
ASSERT(keypad);
memset(keypad, 0, len);
keypad->keypad_info = kpinfo;
output_val = (!!(kpinfo->flags & GPIOKPF_ACTIVE_HIGH)) ^
(!!(kpinfo->flags & GPIOKPF_DRIVE_INACTIVE));
output_cfg = kpinfo->flags & GPIOKPF_DRIVE_INACTIVE ? GPIO_OUTPUT : 0;
for (i = 0; i < kpinfo->noutputs; i++) {
gpio_set(kpinfo->output_gpios[i], output_val);
gpio_config(kpinfo->output_gpios[i], output_cfg);
}
for (i = 0; i < kpinfo->ninputs; i++)
gpio_config(kpinfo->input_gpios[i], GPIO_INPUT);
keypad->current_output = kpinfo->noutputs;
event_init(&keypad->full_scan, false, EVENT_FLAG_AUTOUNSIGNAL);
timer_initialize(&keypad->timer);
timer_set_oneshot(&keypad->timer, 0, gpio_keypad_timer_func, NULL);
/* wait for the keypad to complete one full scan */
event_wait(&keypad->full_scan);
}
int pm8058_gpio_config(int gpio, struct pm8058_gpio *param)
{
int rc;
write_func wr_function = (qwerty_keypad->keypad_info)->wr_func;
unsigned char bank[8];
static int dir_map[] = {
PM8058_GPIO_MODE_OFF,
PM8058_GPIO_MODE_OUTPUT,
PM8058_GPIO_MODE_INPUT,
PM8058_GPIO_MODE_BOTH,
};
if (param == 0) {
dprintf (INFO, "pm8058_gpio struct not defined\n");
return -1;
}
/* Select banks and configure the gpio */
bank[0] = PM8058_GPIO_WRITE |
((param->vin_sel << PM8058_GPIO_VIN_SHIFT) &
PM8058_GPIO_VIN_MASK) |
PM8058_GPIO_MODE_ENABLE;
bank[1] = PM8058_GPIO_WRITE |
((1 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
((dir_map[param->direction] << PM8058_GPIO_MODE_SHIFT) &
PM8058_GPIO_MODE_MASK) |
((param->direction & PM_GPIO_DIR_OUT) ?
PM8058_GPIO_OUT_BUFFER : 0);
bank[2] = PM8058_GPIO_WRITE |
((2 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
((param->pull << PM8058_GPIO_PULL_SHIFT) &
PM8058_GPIO_PULL_MASK);
bank[3] = PM8058_GPIO_WRITE |
((3 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
((param->out_strength << PM8058_GPIO_OUT_STRENGTH_SHIFT) &
PM8058_GPIO_OUT_STRENGTH_MASK);
bank[4] = PM8058_GPIO_WRITE |
((4 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
((param->function << PM8058_GPIO_FUNC_SHIFT) &
PM8058_GPIO_FUNC_MASK);
rc = (*wr_function)(bank, 5, SSBI_REG_ADDR_GPIO(gpio));
if (rc) {
dprintf(INFO, "Failed on 1st ssbi_write(): rc=%d.\n", rc);
return 1;
}
return 0;
}
int pm8058_gpio_config_kypd_drv(int gpio_start, int num_gpios, unsigned mach_id)
{
int rc;
struct pm8058_gpio kypd_drv = {
.direction = PM_GPIO_DIR_OUT,
.pull = PM_GPIO_PULL_NO,
.vin_sel = 2,
.out_strength = PM_GPIO_STRENGTH_LOW,
.function = PM_GPIO_FUNC_1,
.inv_int_pol = 1,
};
if(mach_id == LINUX_MACHTYPE_8660_QT)
kypd_drv.function = PM_GPIO_FUNC_NORMAL;
while (num_gpios--) {
rc = pm8058_gpio_config(gpio_start++, &kypd_drv);
if (rc) {
dprintf(INFO, "FAIL pm8058_gpio_config(): rc=%d.\n", rc);
return rc;
}
}
return 0;
}
int pm8058_gpio_config_kypd_sns(int gpio_start, int num_gpios)
{
int rc;
struct pm8058_gpio kypd_sns = {
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_UP1,
.vin_sel = 2,
.out_strength = PM_GPIO_STRENGTH_NO,
.function = PM_GPIO_FUNC_NORMAL,
.inv_int_pol = 1,
};
while (num_gpios--) {
rc = pm8058_gpio_config(gpio_start++, &kypd_sns);
if (rc) {
dprintf(INFO, "FAIL pm8058_gpio_config(): rc=%d.\n", rc);
return rc;
}
}
return 0;
}
static void ssbi_gpio_init(unsigned int mach_id)
{
unsigned char kypd_cntl_init;
unsigned char kypd_scan_init = 0x20;
int rows = (qwerty_keypad->keypad_info)->rows;
int columns = (qwerty_keypad->keypad_info)->columns;
write_func wr_function = (qwerty_keypad->keypad_info)->wr_func;
unsigned char drv_bits[] = {
0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7 };
unsigned char sns_bits[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3 };
kypd_cntl_init = ((drv_bits[rows] << 2) | (sns_bits[columns] << 5) | (1 << 7));
if ((*wr_function)(&kypd_cntl_init, 1, SSBI_REG_KYPD_CNTL_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
if ((*wr_function)(&kypd_scan_init, 1, SSBI_REG_KYPD_SCAN_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_SCAN register\n");
if(mach_id == LINUX_MACHTYPE_8660_QT)
{
pm8058_gpio_config_kypd_sns(QT_PMIC_GPIO_KYPD_SNS, rows);
pm8058_gpio_config_kypd_drv(QT_PMIC_GPIO_KYPD_DRV, columns, mach_id);
}
else
{
pm8058_gpio_config_kypd_sns(SSBI_OFFSET_ADDR_GPIO_KYPD_SNS, columns);
pm8058_gpio_config_kypd_drv(SSBI_OFFSET_ADDR_GPIO_KYPD_DRV, rows, mach_id);
}
}
static enum handler_return
scan_qwerty_keypad(struct timer *timer, time_t now, void *arg)
{
unsigned int rows = (qwerty_keypad->keypad_info)->rows;
unsigned int columns = (qwerty_keypad->keypad_info)->columns;
unsigned int num_of_ssbi_reads = (qwerty_keypad->keypad_info)->num_of_reads;
read_func rd_function = (qwerty_keypad->keypad_info)->rd_func;
unsigned char column_new_keys = 0x00;
unsigned char column_old_keys = 0x00;
int shift = 0;
static int key_detected = -1;
if ((*rd_function)((qwerty_keypad->keypad_info)->rec_keys, num_of_ssbi_reads,
SSBI_REG_KYPD_REC_DATA_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
if ((*rd_function)((qwerty_keypad->keypad_info)->old_keys, num_of_ssbi_reads,
SSBI_REG_KYPD_OLD_DATA_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
while (rows--) {
columns = qwerty_keypad->keypad_info->columns;
if (((qwerty_keypad->keypad_info)->rec_keys[rows]
!= (qwerty_keypad->keypad_info)->old_keys[rows])
&& ((qwerty_keypad->keypad_info)->rec_keys[rows] != 0x00)
&& ((qwerty_keypad->keypad_info)->old_keys[rows] != 0x00)) {
while (columns--) {
column_new_keys = ((qwerty_keypad->keypad_info)->rec_keys[rows]);
column_old_keys = ((qwerty_keypad->keypad_info)->old_keys[rows]);
if (((0x01 << columns) & (~column_new_keys))
&& !((0x01 << columns) & (~column_old_keys))) {
shift = (rows * 8) + columns;
if ((qwerty_keypad->keypad_info)->keymap[shift]) {
if (shift != key_detected) {
key_detected = shift;
keys_post_event((qwerty_keypad->keypad_info)->keymap[shift], 1);
}
}
}
}
}
}
event_signal(&qwerty_keypad->full_scan, false);
return INT_RESCHEDULE;
}
static enum handler_return
scan_qt_keypad(struct timer *timer, time_t now, void *arg)
{
unsigned int gpio;
unsigned int last_state=0;
unsigned int new_state=0;
unsigned int bits_changed;
static int key_detected=-1;
/* Row GPIOs 8,9,10 are used for sensing here */
for (gpio=8;gpio<=10;gpio++)
{
bool status;
status = pm8058_gpio_get(gpio);
if (status == 0)
new_state |= (1<<(gpio-8));
}
bits_changed = last_state ^ new_state;
if (bits_changed)
{
int shift = 0;
for (unsigned int rows = 0; rows < (qwerty_keypad->keypad_info)->rows; rows++)
{
if ((bits_changed & (1<<rows)) == 0)
continue;
shift = rows * 8 + 3;
}
if ((qwerty_keypad->keypad_info)->keymap[shift])
{
if (shift != key_detected)
{
key_detected = shift;
keys_post_event((qwerty_keypad->keypad_info)->keymap[shift], 1);
timer_set_oneshot(timer,(qwerty_keypad->keypad_info)->poll_time,
scan_qt_keypad, NULL);
return INT_RESCHEDULE;
}
}
}
event_signal(&qwerty_keypad->full_scan, false);
return INT_RESCHEDULE;
}
void ssbi_keypad_init(struct qwerty_keypad_info *qwerty_kp)
{
unsigned int mach_id;
int len;
len = sizeof(struct gpio_qwerty_kp);
qwerty_keypad = malloc(len);
ASSERT(qwerty_keypad);
memset(qwerty_keypad, 0, len);
qwerty_keypad->keypad_info = qwerty_kp;
event_init(&qwerty_keypad->full_scan, false, EVENT_FLAG_AUTOUNSIGNAL);
timer_initialize(&qwerty_keypad->timer);
mach_id = board_machtype();
ssbi_gpio_init(mach_id);
if(mach_id == LINUX_MACHTYPE_8660_QT)
{
mdelay((qwerty_keypad->keypad_info)->settle_time);
#ifdef QT_8660_KEYPAD_HW_BUG
timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qt_keypad, NULL);
#endif
}
else
timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qwerty_keypad, NULL);
/* wait for the keypad to complete one full scan */
event_wait(&qwerty_keypad->full_scan);
}
static enum handler_return
scan_qwerty_gpio_keypad(struct timer *timer, time_t now, void *arg)
{
int i=0;
int num =0;
uint8_t key_status;
struct qwerty_keypad_info *keypad = qwerty_keypad->keypad_info;
num = keypad->mapsize;
for(i=0; i < num; i++)
{
/*continue if not interested in key*/
if(!keypad->keymap[i])
continue;
/*read key gpio*/
keypad->key_gpio_get(keypad->gpiomap[i], &key_status);
/*Post event if key pressed*/
if(key_status)
{
keys_post_event(keypad->keymap[i], 1);
goto done;
}
}
done:
event_signal(&qwerty_keypad->full_scan, false);
return INT_RESCHEDULE;
}
void ssbi_gpio_keypad_init(struct qwerty_keypad_info *qwerty_kp)
{
int len;
len = sizeof(struct gpio_qwerty_kp);
qwerty_keypad = malloc(len);
ASSERT(qwerty_keypad);
memset(qwerty_keypad, 0, len);
qwerty_keypad->keypad_info = qwerty_kp;
event_init(&qwerty_keypad->full_scan, false, EVENT_FLAG_AUTOUNSIGNAL);
timer_initialize(&qwerty_keypad->timer);
timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qwerty_gpio_keypad, NULL);
/* wait for the keypad to complete one full scan */
event_wait(&qwerty_keypad->full_scan);
}
void pmic_write(unsigned address, unsigned data)
{
write_func wr_function = &i2c_ssbi_write_bytes;
if (wr_function == NULL)
return;
if ((*wr_function)((unsigned char *) &data, 1, address))
dprintf (CRITICAL, "Error in initializing register\n");
}
void toshiba_pmic_gpio_init(unsigned gpio)
{
pmic_write(gpio,0x85);
pmic_write(gpio,0x98);
pmic_write(gpio,0xB8);
pmic_write(gpio,0xC6);
}
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <bits.h>
#include <debug.h>
#include <string.h>
#include <dev/keys.h>
static unsigned long key_bitmap[BITMAP_NUM_WORDS(MAX_KEYS)];
void keys_init(void)
{
memset(key_bitmap, 0, sizeof(key_bitmap));
}
void keys_post_event(uint16_t code, int16_t value)
{
if (code >= MAX_KEYS) {
dprintf(INFO, "Invalid keycode posted: %d\n", code);
return;
}
/* TODO: Implement an actual event queue if it becomes necessary */
if (value)
bitmap_set(key_bitmap, code);
else
bitmap_clear(key_bitmap, code);
// dprintf(INFO, "key state change: %d %d\n", code, value);
}
int keys_get_state(uint16_t code)
{
if (code >= MAX_KEYS) {
dprintf(INFO, "Invalid keycode requested: %d\n", code);
return -1;
}
return bitmap_test(key_bitmap, code);
}
+10
View File
@@ -0,0 +1,10 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/keys.o
ifeq ($(KEYS_USE_GPIO_KEYPAD),1)
OBJS += \
$(LOCAL_DIR)/gpio_keypad.o
endif
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _DEV_NET_SMC91C96_H
#define _DEV_NET_SMC91C96_H
void smc91c96_init(void);
#endif
@@ -0,0 +1,8 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
INCLUDES += \
-I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/smc91c96.o
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <debug.h>
#include <printf.h>
#include <dev/net/smc91c96.h>
#include "smc91c96_p.h"
#if !defined(SMC91C96_BASE_ADDR) || !defined(SMC91C96_IRQ)
#error need to define SMC91C96_BASE_ADDR and SMC91C96_IRQ in project
#endif
static addr_t smc91c96_base = SMC91C96_BASE_ADDR;
static uint8_t mac_addr[6];
#define SMC_REG16(reg) ((volatile uint16_t *)(smc91c96_base + (reg)))
#define SMC_REG8(reg) ((volatile uint8_t *)(smc91c96_base + (reg)))
static inline void smc_bank(int bank)
{
*SMC_REG16(SMC_BSR) = bank;
}
void smc91c96_init(void)
{
int i;
TRACE;
// try to detect it
if ((*SMC_REG16(SMC_BSR) & 0xff00) != 0x3300) {
TRACEF("didn't see smc91c96 chip at 0x%x\n", (unsigned int)smc91c96_base);
}
// read revision
smc_bank(3);
TRACEF("detected, revision 0x%x\n", *SMC_REG16(SMC_REV));
// read in the mac address
smc_bank(1);
for (i=0; i < 6; i++) {
mac_addr[i] = *SMC_REG8(SMC_IAR0 + i);
}
TRACEF("mac address %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);
smc_bank(0);
}
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __SMC91C96_P_H
#define __SMC91C96_P_H
// LAN91C96 stuffs
/* registers */
#define SMC_BSR 14
/* bank 0 */
#define SMC_TCR 0
#define SMC_EPHSR 2
#define SMC_RCR 4
#define SMC_ECR 6
#define SMC_MIR 8
#define SMC_MCR 10
/* bank 1 */
#define SMC_CR 0
#define SMC_BAR 2
#define SMC_IAR0 4
#define SMC_IAR1 5
#define SMC_IAR2 6
#define SMC_IAR3 7
#define SMC_IAR4 8
#define SMC_IAR5 9
#define SMC_GPR 10
#define SMC_CTR 12
/* bank 2 */
#define SMC_MMUCR 0
#define SMC_AUTOTX 1
#define SMC_PNR 2
#define SMC_ARR 3
#define SMC_FIFO 4
#define SMC_PTR 6
#define SMC_DATA0 8
#define SMC_DATA1 10
#define SMC_IST 12
#define SMC_ACK 12
#define SMC_MSK 13
/* bank 3 */
#define SMC_MT0 0
#define SMC_MT1 1
#define SMC_MT2 2
#define SMC_MT3 3
#define SMC_MT4 4
#define SMC_MT5 5
#define SMC_MT6 6
#define SMC_MT7 7
#define SMC_MGMT 8
#define SMC_REV 10
#define SMC_ERCV 12
#endif
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of The Linux Foundation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LCDC_TRULY_H_
#define _LCDC_TRULY_H_
#define DISPLAY_RESET 90
#define BACKLIGHT_EN 89
#define SPI_MOSI 19
#define SPI_SCLK 20
#define SPI_CS 21
#define LCD_LDO_2V8 35
#define LCD_LDO_1V8 58
#endif
@@ -0,0 +1,223 @@
/*
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of The Linux Foundation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <msm_panel.h>
#include <platform/gpio.h>
#include <debug.h>
#include <err.h>
#include "lcdc_truly.h"
extern void spi_bit_bang_write(uint8_t, uint8_t, uint8_t, uint8_t);
static char data1[] = { 0xff, 0x83, 0x57, };
static char data2[] = { 0x03, };
static char data3[] = { 0x00, 0x13, 0x1C, 0x1C, 0x83, 0x48, };
static char data4[] = { 0x43, 0x06, 0x06, 0x06, };
static char data5[] = { 0x53, };
static char data6[] = { 0x02, 0x40, 0x00, 0x2a, 0x2a, 0x0d, 0x3f, };
static char data7[] = { 0x70, 0x50, 0x01, 0x3c, 0xe8, 0x08, };
static char data8[] = { 0x17, 0x0f, };
static char data9[] = { 0x60};
static char data10[] = { 0x00, 0x13, 0x1a, 0x29, 0x2d, 0x41, 0x49,
0x52, 0x48, 0x41, 0x3c, 0x33, 0x30, 0x1c,
0x19, 0x03, 0x00, 0x13, 0x1a, 0x29, 0x2d,
0x41, 0x49, 0x52, 0x48, 0x41, 0x3c, 0x33,
0x31, 0x1c, 0x19, 0x03, 0x00, 0x01,
};
static char data11[] = { 0x40, };
static void lcdc_truly_panel_power(int on)
{
uint32_t func = 0;
uint32_t pull = 0;
uint32_t drv = 0;
uint32_t dir = 0;
dprintf(SPEW, "lcdc_truly_panel_power on = %d\n", on);
if (on) {
func = 0;
dir = GPIO_OUTPUT;
pull = GPIO_NO_PULL;
drv = GPIO_2MA;
/* config SPI, RESET and Backlight */
gpio_tlmm_config(GPIO_CFG(SPI_MOSI, func, dir, pull, drv), 0);
gpio_tlmm_config(GPIO_CFG(SPI_SCLK, func, dir, pull, drv), 0);
gpio_tlmm_config(GPIO_CFG(SPI_CS, func, dir, pull, drv), 0);
gpio_tlmm_config(GPIO_CFG(BACKLIGHT_EN, func, dir, pull, drv), 0);
gpio_tlmm_config(GPIO_CFG(DISPLAY_RESET, func, dir, pull, drv), 0);
gpio_tlmm_config(GPIO_CFG(LCD_LDO_2V8, func, dir, pull, drv), 0);
gpio_tlmm_config(GPIO_CFG(LCD_LDO_1V8, func, dir, pull, drv), 0);
gpio_config(SPI_MOSI, GPIO_OUTPUT);
gpio_config(SPI_SCLK, GPIO_OUTPUT);
gpio_config(SPI_CS, GPIO_OUTPUT);
gpio_config(BACKLIGHT_EN, GPIO_OUTPUT);
gpio_config(DISPLAY_RESET, GPIO_OUTPUT);
gpio_config(LCD_LDO_2V8, GPIO_OUTPUT);
gpio_config(LCD_LDO_1V8, GPIO_OUTPUT);
/* turn on backlight */
gpio_set(BACKLIGHT_EN, 1);
/* turn on power */
gpio_set(LCD_LDO_1V8, 1);
gpio_set(LCD_LDO_2V8, 1);
/* reset */
gpio_set(DISPLAY_RESET, 1);
/*
* H/w requires delay between toggle
* reset pin
*/
mdelay(20);
gpio_set(DISPLAY_RESET, 0);
mdelay(20);
gpio_set(DISPLAY_RESET, 1);
mdelay(20);
} else {
/* turn off backlight */
gpio_set(BACKLIGHT_EN, 0);
gpio_set(DISPLAY_RESET, 0);
/* turn off power */
gpio_set(LCD_LDO_1V8, 0);
gpio_set(LCD_LDO_2V8, 0);
}
return;
}
static int truly_spi_write(char cmd, char *data, int num)
{
int i;
gpio_set(SPI_CS, 0); /* cs low */
/* command byte first */
spi_bit_bang_write(SPI_SCLK, SPI_MOSI, 0, cmd);
/* followed by parameter bytes */
for(i = 0; i < num; i++) {
if(data)
spi_bit_bang_write(SPI_SCLK, SPI_MOSI, 1, data[i]);
}
gpio_set(SPI_MOSI, 1); /* mosi high */
gpio_set(SPI_CS, 1); /* cs high */
/*
* H/W needs delay for gpio's to turn high
*/
udelay(10);
return 0;
}
void lcdc_truly_disp_on(void)
{
int i;
dprintf(SPEW, "lcdc_truly_disp_on\n");
gpio_set(SPI_CS, 1); /* cs high */
/*
* This function uses delays as defined by the panel
* vendor before writing to registers
*/
truly_spi_write(0xb9, data1, sizeof(data1));
mdelay(20);
truly_spi_write(0xcc, data2, sizeof(data2));
truly_spi_write(0xb1, data3, sizeof(data3));
truly_spi_write(0xb3, data4, sizeof(data4));
truly_spi_write(0xb6, data5, sizeof(data5));
truly_spi_write(0xb4, data6, sizeof(data6));
truly_spi_write(0xc0, data7, sizeof(data7));
truly_spi_write(0xe3, data8, sizeof(data8));
truly_spi_write(0x3a, data9, sizeof(data9));
truly_spi_write(0xe0, data10, sizeof(data10));
truly_spi_write(0x36, data11, sizeof(data11));
truly_spi_write(0x11, NULL, 0);
mdelay(150);
truly_spi_write(0x29, NULL, 0);
mdelay(25);
}
void lcdc_truly_disp_off(void)
{
dprintf(SPEW, "lcdc_truly_disp_off\n");
truly_spi_write(0x28, NULL, 0);
mdelay(5);
truly_spi_write(0x10, NULL, 0);
}
int lcdc_truly_panel_on(int on)
{
dprintf(SPEW, "lcdc_truly_panel_on\n");
if (on) {
lcdc_truly_panel_power(1);
lcdc_truly_disp_on();
} else {
lcdc_truly_panel_power(0);
lcdc_truly_disp_off();
}
return NO_ERROR;
}
int lcdc_truly_hvga_on()
{
return NO_ERROR;
}
int lcdc_truly_hvga_off()
{
return NO_ERROR;
}
void lcdc_truly_hvga_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
pinfo->xres = 320;
pinfo->yres = 480;
pinfo->type = LCDC_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 16;
pinfo->clk_rate = 10240000;
pinfo->lcdc.h_pulse_width = 8;
pinfo->lcdc.h_back_porch = 16;
pinfo->lcdc.h_front_porch = 4;
pinfo->lcdc.hsync_skew = 0;
pinfo->lcdc.v_pulse_width = 1;
pinfo->lcdc.v_back_porch = 7;
pinfo->lcdc.v_front_porch = 3;
pinfo->on = lcdc_truly_hvga_on;
pinfo->off = lcdc_truly_hvga_off;
return;
}
@@ -0,0 +1,76 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <msm_panel.h>
#include <err.h>
int lvds_chimei_wxga_config(void *pdata)
{
return NO_ERROR;
}
int lvds_chimei_wxga_on()
{
return NO_ERROR;
}
int lvds_chimei_wxga_off()
{
return NO_ERROR;
}
void lvds_chimei_wxga_init(struct msm_panel_info *pinfo)
{
pinfo->xres = 1364;
pinfo->yres = 768;
pinfo->type = LVDS_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->clk_rate = 75000000;
pinfo->lcdc.h_back_porch = 0;
pinfo->lcdc.h_front_porch = 194;
pinfo->lcdc.h_pulse_width = 40;
pinfo->lcdc.v_back_porch = 0;
pinfo->lcdc.v_front_porch = 38;
pinfo->lcdc.v_pulse_width = 20;
pinfo->lcdc.underflow_clr = 0xff;
pinfo->lcdc.hsync_skew = 0;
pinfo->lvds.channel_mode = LVDS_SINGLE_CHANNEL_MODE;
/* Set border color, padding only for reducing active display region */
pinfo->lcdc.border_clr = 0x0;
pinfo->lcdc.xres_pad = 0;
pinfo->lcdc.yres_pad = 0;
pinfo->on = lvds_chimei_wxga_on;
pinfo->off = lvds_chimei_wxga_off;
pinfo->config = lvds_chimei_wxga_config;
}
@@ -0,0 +1,228 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <msm_panel.h>
#include <mipi_dsi.h>
#include <sys/types.h>
#include <err.h>
#include <reg.h>
#include <debug.h>
#include <platform/iomap.h>
#include <mdp4.h>
#include <clock.h>
#include "mipi_tc358764_dsi2lvds.h"
int mipi_chimei_video_wxga_early_config(void *pdata)
{
uint32_t tmp;
uint32_t reg = DSI_LANE_CTRL;
struct msm_panel_info *pinfo = (struct msm_panel_info *)pdata;
/* Force DSI-clock ON */
tmp = readl_relaxed(reg);
tmp |= (1<<28);
writel_relaxed(tmp, reg);
mipi_d2l_dsi_init_sequence(pinfo);
}
int mipi_chimei_video_wxga_config(void *pdata)
{
int ret = NO_ERROR;
struct lcdc_panel_info *lcdc = NULL;
struct msm_panel_info *pinfo = (struct msm_panel_info *)pdata;
unsigned char lane_en = 0x0F; /* 4 Lanes */
unsigned long low_pwr_stop_mode = 0;
unsigned char eof_bllp_pwr = 0;
unsigned char interleav = 0;
if (pinfo == NULL)
return ERR_INVALID_ARGS;
lcdc = &(pinfo->lcdc);
if (lcdc == NULL)
return ERR_INVALID_ARGS;
ret = mipi_dsi_video_mode_config((pinfo->xres + lcdc->xres_pad),
(pinfo->yres + lcdc->yres_pad),
(pinfo->xres),
(pinfo->yres),
(lcdc->h_front_porch),
(lcdc->h_back_porch + lcdc->h_pulse_width),
(lcdc->v_front_porch),
(lcdc->v_back_porch + lcdc->v_pulse_width),
(lcdc->h_pulse_width),
(lcdc->v_pulse_width),
pinfo->mipi.dst_format,
pinfo->mipi.traffic_mode,
lane_en,
low_pwr_stop_mode,
eof_bllp_pwr,
interleav);
return ret;
}
int mipi_chimei_video_wxga_on(void)
{
int ret = 0;
return ret;
}
int mipi_chimei_video_wxga_off(void)
{
int ret = 0;
return ret;
}
static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
/* DSIPHY_REGULATOR_CTRL */
.regulator = {0x03, 0x0a, 0x04, 0x00, 0x20}, /* common 8960 */
/* DSIPHY_CTRL */
.ctrl = {0x5f, 0x00, 0x00, 0x10}, /* common 8960 */
/* DSIPHY_STRENGTH_CTRL */
.strength = {0xff, 0x00, 0x06, 0x00}, /* common 8960 */
/* DSIPHY_TIMING_CTRL */
.timing = { 0xB6, 0x8D, 0x1E, /* panel specific */
0, /* DSIPHY_TIMING_CTRL_3 = 0 */
0x21, 0x95, 0x21, 0x8F, 0x21, 0x03, 0x04}, /* panel specific */
/* DSIPHY_PLL_CTRL */
.pll = { 0x01, /* common 8960 */
/* VCO */
0xD8, 0x01, 0x1A, /* panel specific */
0x00, 0x50, 0x48, 0x63,
0x71, 0x0F, 0x03, /* Clocks dividers */
0x00, 0x14, 0x03, 0x00, 0x02, /* common 8960 */
0x00, 0x20, 0x00, 0x01 }, /* common 8960 */
};
void mipi_chimei_video_wxga_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
dprintf(INFO, "mipi-dsi chimei wxga (1366x768) driver ver 1.0.\n");
/* Landscape */
pinfo->xres = 1366;
pinfo->yres = 768;
pinfo->type = MIPI_VIDEO_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24; /* RGB888 = 24 bits-per-pixel */
/* bitclk */
pinfo->clk_rate = 473400000; /* 473.4 MHZ Calculated */
/*
* this panel is operated by DE,
* vsycn and hsync are ignored
*/
pinfo->lcdc.h_front_porch = 96+2;/* thfp */
pinfo->lcdc.h_back_porch = 88; /* thb */
pinfo->lcdc.h_pulse_width = 40; /* thpw */
pinfo->lcdc.v_front_porch = 15; /* tvfp */
pinfo->lcdc.v_back_porch = 23; /* tvb */
pinfo->lcdc.v_pulse_width = 20; /* tvpw */
pinfo->lcdc.border_clr = 0; /* black */
pinfo->lcdc.underflow_clr = 0xff; /* blue */
pinfo->lcdc.hsync_skew = 0;
/* mipi - general */
pinfo->mipi.vc = 0; /* virtual channel */
pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
pinfo->mipi.tx_eot_append = true;
pinfo->mipi.t_clk_post = 34; /* Calculated */
pinfo->mipi.t_clk_pre = 64; /* Calculated */
pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
/* Four lanes are recomended for 1366x768 at 60 frames per second */
pinfo->mipi.frame_rate = 60; /* 60 frames per second */
pinfo->mipi.data_lane0 = true;
pinfo->mipi.data_lane1 = true;
pinfo->mipi.data_lane2 = true;
pinfo->mipi.data_lane3 = true;
pinfo->mipi.mode = DSI_VIDEO_MODE;
/*
* Note: The CMI panel input is RGB888,
* thus the DSI-to-LVDS bridge output is RGB888.
* This parameter selects the DSI-Core output to the bridge.
*/
pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
/* mipi - video mode */
pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
pinfo->mipi.pulse_mode_hsa_he = false; /* sync mode */
pinfo->mipi.hfp_power_stop = false;
pinfo->mipi.hbp_power_stop = false;
pinfo->mipi.hsa_power_stop = false;
pinfo->mipi.eof_bllp_power_stop = false;
pinfo->mipi.bllp_power_stop = false;
/* mipi - command mode */
pinfo->mipi.te_sel = 1; /* TE from vsycn gpio */
pinfo->mipi.interleave_max = 1;
/* The bridge supports only Generic Read/Write commands */
pinfo->mipi.insert_dcs_cmd = false;
pinfo->mipi.wr_mem_continue = 0;
pinfo->mipi.wr_mem_start = 0;
pinfo->mipi.stream = false; /* dma_p */
pinfo->mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
/*
* toshiba d2l chip does not need max_pkt_szie dcs cmd
* client reply len is directly configure through
* RDPKTLN register (0x0404)
*/
pinfo->mipi.no_max_pkt_size = 1;
pinfo->mipi.force_clk_lane_hs = 1;
pinfo->mipi.num_of_lanes = 4;
pinfo->mipi.panel_cmds = NULL; /* use in mipi_dsi_panel_initialize() */
pinfo->mipi.num_of_panel_cmds = 0;
/* Provide config/on/off callbacks */
pinfo->on = mipi_chimei_video_wxga_on;
pinfo->off = mipi_chimei_video_wxga_off;
pinfo->config = mipi_chimei_video_wxga_config;
pinfo->early_config = mipi_chimei_video_wxga_early_config;
return;
}
@@ -0,0 +1,77 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <msm_panel.h>
#include <mipi_dsi.h>
#include <sys/types.h>
#include <err.h>
#include <reg.h>
#include <debug.h>
#include <target/display.h>
#include <dev/gpio.h>
int mipi_nt35510_panel_dsi_config(int on)
{
if (on) {
gpio_config(96, GPIO_OUTPUT);
/*
* As per the specification follow the sequence to put lcd
* backlight in one wire mode.
*/
gpio_set(96, 0x1);
udelay(190);
gpio_set(96, 0x0);
udelay(286);
gpio_set(96, 0x1);
udelay(50);
gpio_config(35, GPIO_OUTPUT);
gpio_set(35, 0x1);
gpio_config(40, GPIO_OUTPUT);
gpio_set(40, 0x1);
gpio_config(85, GPIO_OUTPUT);
gpio_set(85, 0x1);
mdelay(20);
gpio_set(85, 0x0);
mdelay(20);
gpio_set(85, 0x1);
mdelay(20);
} else {
if (!target_cont_splash_screen()) {
gpio_set(96, 0x0);
gpio_set(35, 0x0);
gpio_set(40, 0x0);
}
}
return 0;
}
@@ -0,0 +1,345 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <msm_panel.h>
#include <mipi_dsi.h>
#include <sys/types.h>
#include <err.h>
#include <reg.h>
#include <debug.h>
#include <target/display.h>
/* MIPI NT35510 panel commands */
static char exit_sleep[4] = {0x11, 0x00, 0x05, 0x80};
static char display_on[4] = {0x29, 0x00, 0x05, 0x80};
static char write_ram[4] = {0x2c, 0x00, 0x05, 0x80}; /* write ram */
static char cmd0[12] = {
0x06, 0x00, 0x29, 0xc0, 0xF0, 0x55, 0xAA, 0x52,
0x08, 0x01, 0xff, 0xff,
};
static char cmd1[8] = {
0x04, 0x00, 0x29, 0xc0, 0xBC, 0x00, 0xA0, 0x00,
};
static char cmd2[8] = {
0x04, 0x00, 0x29, 0xc0, 0xBD, 0x00, 0xA0, 0x00,
};
static char cmd3[8] = {
0x03, 0x00, 0x29, 0xc0, 0xBE, 0x00, 0x79, 0xff,
};
static char cmd4[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD1, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char cmd5[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD2, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char cmd6[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD3, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char cmd7[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD4, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char cmd8[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD5, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char cmd9[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD6, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char cmd10[8] = {
0x04, 0x00, 0x29, 0xc0, 0xB0, 0x0A, 0x0A, 0x0A,
};
static char cmd11[8] = {
0x04, 0x00, 0x29, 0xc0, 0xB1, 0x0A, 0x0A, 0x0A,
};
static char cmd12[8] = {
0x04, 0x00, 0x29, 0xc0, 0xBA, 0x24, 0x24, 0x24,
};
static char cmd13[8] = {
0x04, 0x00, 0x29, 0xc0, 0xB9, 0x24, 0x24, 0x24,
};
static char cmd14[8] = {
0x04, 0x00, 0x29, 0xc0, 0xB8, 0x24, 0x24, 0x24,
};
static char cmd15[12] = {
0x06, 0x00, 0x29, 0xc0, 0xF0, 0x55, 0xAA, 0x52,
0x08, 0x00, 0xff, 0xff,
};
static char cmd16[8] = {
0x02, 0x00, 0x29, 0xc0, 0xB3, 0x00, 0xff, 0xff,
};
static char cmd17[8] = {
0x02, 0x00, 0x29, 0xc0, 0xB4, 0x10, 0xff, 0xff,
};
static char cmd18[8] = {
0x02, 0x00, 0x29, 0xc0, 0xB6, 0x02, 0xff, 0xff,
};
static char cmd19[8] = {
0x03, 0x00, 0x29, 0xc0, 0xB1, 0xEC, 0x00, 0xff,
};
static char cmd19_rotate[8] = {
0x03, 0x00, 0x29, 0xc0, 0xB1, 0xEC, 0x06, 0xff,
};
static char cmd20[8] = {
0x04, 0x00, 0x29, 0xc0, 0xBC, 0x05, 0x05, 0x05,
};
static char cmd21[8] = {
0x03, 0x00, 0x29, 0xc0, 0xB7, 0x20, 0x20, 0xff,
};
static char cmd22[12] = {
0x05, 0x00, 0x29, 0xc0, 0xB8, 0x01, 0x03, 0x03,
0x03, 0xff, 0xff, 0xff,
};
static char cmd23[24] = {
0x13, 0x00, 0x29, 0xc0, 0xC8, 0x01, 0x00, 0x78,
0x50, 0x78, 0x50, 0x78,
0x50, 0x78, 0x50, 0xC8,
0x3C, 0x3C, 0xC8, 0xC8,
0x3C, 0x3C, 0xC8, 0xff,
};
static char cmd24[12] = {
0x06, 0x00, 0x29, 0xc0, 0xBD, 0x01, 0x84, 0x07,
0x31, 0x00, 0xff, 0xff,
};
static char cmd25[12] = {
0x06, 0x00, 0x29, 0xc0, 0xBE, 0x01, 0x84, 0x07,
0x31, 0x00, 0xff, 0xff,
};
static char cmd26[12] = {
0x06, 0x00, 0x29, 0xc0, 0xBF, 0x01, 0x84, 0x07,
0x31, 0x00, 0xff, 0xff,
};
static char cmd27[8] = {
0x02, 0x00, 0x29, 0xc0, 0x35, 0x00, 0xff, 0xff,
};
static char config_MADCTL[4] = {0x36, 0x00, 0x15, 0x80};
static struct mipi_dsi_cmd nt35510_panel_cmd_mode_cmds[] = {
{sizeof(cmd0), cmd0},
{sizeof(cmd1), cmd1},
{sizeof(cmd2), cmd2},
{sizeof(cmd3), cmd3},
{sizeof(cmd4), cmd4},
{sizeof(cmd5), cmd5},
{sizeof(cmd6), cmd6},
{sizeof(cmd7), cmd7},
{sizeof(cmd8), cmd8},
{sizeof(cmd9), cmd9},
{sizeof(cmd10), cmd10},
{sizeof(cmd11), cmd11},
{sizeof(cmd12), cmd12},
{sizeof(cmd13), cmd13},
{sizeof(cmd14), cmd14},
{sizeof(cmd15), cmd15},
{sizeof(cmd16), cmd16},
{sizeof(cmd17), cmd17},
{sizeof(cmd18), cmd18},
{sizeof(cmd19), cmd19},
{sizeof(cmd20), cmd20},
{sizeof(cmd21), cmd21},
{sizeof(cmd22), cmd22},
{sizeof(cmd23), cmd23},
{sizeof(cmd24), cmd24},
{sizeof(cmd25), cmd25},
{sizeof(cmd26), cmd26},
{sizeof(cmd27), cmd27},
{sizeof(exit_sleep), exit_sleep},
{sizeof(display_on), display_on},
{sizeof(config_MADCTL), config_MADCTL},
{sizeof(write_ram), write_ram},
};
static struct mipi_dsi_cmd nt35510_cmd_rotate_cmds[] = {
{sizeof(cmd19_rotate), cmd19_rotate},
};
int mipi_nt35510_cmd_wvga_on()
{
int ret = NO_ERROR;
return ret;
}
int mipi_nt35510_cmd_wvga_off()
{
int ret = NO_ERROR;
return ret;
}
int mipi_nt35510_cmd_wvga_rotate()
{
int ret = NO_ERROR;
ret = mipi_dsi_cmds_tx(nt35510_cmd_rotate_cmds, ARRAY_SIZE(nt35510_cmd_rotate_cmds));
return ret;
}
int mipi_nt35510_cmd_wvga_config(void *pdata)
{
int ret = NO_ERROR;
struct msm_panel_info *pinfo = (struct msm_panel_info *) pdata;
if (pinfo == NULL)
return ERR_INVALID_ARGS;
ret = mipi_dsi_cmd_mode_config((pinfo->xres),
(pinfo->yres),
(pinfo->xres),
(pinfo->yres),
pinfo->mipi.dst_format,
pinfo->mipi.traffic_mode);
return ret;
}
struct mipi_dsi_phy_ctrl dsi_cmd_mode_phy_db = {
/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
{0x03, 0x01, 0x01, 0x00}, /* regulator */
/* timing */
{0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22,
0x90, 0x18, 0x03, 0x04},
{0x7f, 0x00, 0x00, 0x00}, /* phy ctrl */
{0xbb, 0x02, 0x06, 0x00}, /* strength */
/* pll control */
{0x00, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
0x01, 0x0f, 0x07, /* --> Two lane configuration */
0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
};
void mipi_nt35510_cmd_wvga_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
pinfo->xres = NT35510_MIPI_FB_WIDTH;
pinfo->yres = NT35510_MIPI_FB_HEIGHT;
pinfo->mipi.num_of_lanes = 2;
pinfo->type = MIPI_CMD_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->clk_rate = 499000000;
pinfo->mipi.mode = DSI_CMD_MODE;
pinfo->mipi.traffic_mode = 0;
pinfo->mipi.dst_format = 0;
pinfo->mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
pinfo->mipi.tx_eot_append = TRUE;
pinfo->mipi.lane_swap = 1;
pinfo->mipi.panel_cmds = nt35510_panel_cmd_mode_cmds;
pinfo->mipi.num_of_panel_cmds = \
ARRAY_SIZE(nt35510_panel_cmd_mode_cmds);
pinfo->on = mipi_nt35510_cmd_wvga_on;
pinfo->off = mipi_nt35510_cmd_wvga_off;
pinfo->config = mipi_nt35510_cmd_wvga_config;
pinfo->rotate = mipi_nt35510_cmd_wvga_rotate;
return;
}
@@ -0,0 +1,372 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <msm_panel.h>
#include <mipi_dsi.h>
#include <sys/types.h>
#include <err.h>
#include <reg.h>
#include <debug.h>
#include <platform/iomap.h>
#include <target/display.h>
#include <dev/gpio.h>
/* MIPI NT35510 panel commands */
static char exit_sleep[4] = {0x11, 0x00, 0x09, 0x80};
static char display_on[4] = {0x29, 0x00, 0x05, 0x80};
static char video0[12] = {
0x06, 0x00, 0x29, 0xc0, 0xF0, 0x55, 0xAA, 0x52,
0x08, 0x01, 0xff, 0xff,
};
static char video1[8] = {
0x04, 0x00, 0x29, 0xc0, 0xBC, 0x00, 0xA0, 0x00,
};
static char video2[8] = {
0x04, 0x00, 0x29, 0xc0, 0xBD, 0x00, 0xA0, 0x00,
};
static char video3[8] = {
0x03, 0x00, 0x29, 0xc0, 0xBE, 0x00, 0x79, 0xff,
};
static char video4[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD1, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char video5[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD2, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff
};
static char video6[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD3, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char video7[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD4, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char video8[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD5, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char video9[60] = {
0x35, 0x00, 0x29, 0xc0, 0xD6, 0x00, 0x00, 0x00,
0x14, 0x00, 0x32, 0x00,
0x4F, 0x00, 0x65, 0x00,
0x8B, 0x00, 0xA8, 0x00,
0xD5, 0x00, 0xF7, 0x01,
0x2B, 0x01, 0x54, 0x01,
0x8E, 0x01, 0xBB, 0x01,
0xBC, 0x01, 0xE3, 0x02,
0x08, 0x02, 0x1C, 0x02,
0x39, 0x02, 0x4F, 0x02,
0x76, 0x02, 0xA3, 0x02,
0xE3, 0x03, 0x12, 0x03,
0x4C, 0x03, 0x66, 0x03,
0x9A, 0xff, 0xff, 0xff,
};
static char video10[8] = {
0x04, 0x00, 0x29, 0xc0, 0xB0, 0x0A, 0x0A, 0x0A,
};
static char video11[8] = {
0x04, 0x00, 0x29, 0xc0, 0xB1, 0x0A, 0x0A, 0x0A,
};
static char video12[8] = {
0x04, 0x00, 0x29, 0xc0, 0xBA, 0x24, 0x24, 0x24,
};
static char video13[8] = {
0x04, 0x00, 0x29, 0xc0, 0xB9, 0x24, 0x24, 0x24,
};
static char video14[8] = {
0x04, 0x00, 0x29, 0xc0, 0xB8, 0x24, 0x24, 0x24,
};
static char video15[12] = {
0x06, 0x00, 0x29, 0xc0, 0xF0, 0x55, 0xAA, 0x52,
0x08, 0x00, 0xff, 0xff,
};
static char video16[8] = {
0x02, 0x00, 0x29, 0xc0, 0xB3, 0x00, 0xff, 0xff,
};
static char video17[8] = {
0x02, 0x00, 0x29, 0xc0, 0xB4, 0x10, 0xff, 0xff,
};
static char video18[8] = {
0x02, 0x00, 0x29, 0xc0, 0xB6, 0x02, 0xff, 0xff,
};
static char video19[8] = {
0x03, 0x00, 0x29, 0xc0, 0xB1, 0xFC, 0x00, 0xff,
};
static char video19_rotate[8] = {
0x03, 0x00, 0x29, 0xc0, 0xB1, 0xFC, 0x06, 0xff,
};
static char video20[8] = {
0x04, 0x00, 0x29, 0xc0, 0xBC, 0x05, 0x05, 0x05,
};
static char video21[8] = {
0x03, 0x00, 0x29, 0xc0, 0xB7, 0x20, 0x20, 0xff,
};
static char video22[12] = {
0x05, 0x00, 0x29, 0xc0, 0xB8, 0x01, 0x03, 0x03,
0x03, 0xff, 0xff, 0xff,
};
static char video23[24] = {
0x13, 0x00, 0x29, 0xc0, 0xC8, 0x01, 0x00, 0x78,
0x50, 0x78, 0x50, 0x78,
0x50, 0x78, 0x50, 0xC8,
0x3C, 0x3C, 0xC8, 0xC8,
0x3C, 0x3C, 0xC8, 0xff,
};
static char video24[12] = {
0x06, 0x00, 0x29, 0xc0, 0xBD, 0x01, 0x84, 0x07,
0x31, 0x00, 0xff, 0xff,
};
static char video25[12] = {
0x06, 0x00, 0x29, 0xc0, 0xBE, 0x01, 0x84, 0x07,
0x31, 0x00, 0xff, 0xff,
};
static char video26[12] = {
0x06, 0x00, 0x29, 0xc0, 0xBF, 0x01, 0x84, 0x07,
0x31, 0x00, 0xff, 0xff
};
static char video27[8] = {
0x02, 0x00, 0x29, 0xc0, 0x35, 0x00, 0xff, 0xff,
};
static struct mipi_dsi_cmd nt35510_panel_video_mode_cmds[] = {
{sizeof(video0), video0},
{sizeof(video1), video1},
{sizeof(video2), video2},
{sizeof(video3), video3},
{sizeof(video4), video4},
{sizeof(video5), video5},
{sizeof(video6), video6},
{sizeof(video7), video7},
{sizeof(video8), video8},
{sizeof(video9), video9},
{sizeof(video10), video10},
{sizeof(video11), video11},
{sizeof(video12), video12},
{sizeof(video13), video13},
{sizeof(video14), video14},
{sizeof(video15), video15},
{sizeof(video16), video16},
{sizeof(video17), video17},
{sizeof(video18), video18},
{sizeof(video19), video19},
{sizeof(video20), video20},
{sizeof(video21), video21},
{sizeof(video22), video22},
{sizeof(video23), video23},
{sizeof(video24), video24},
{sizeof(video25), video25},
{sizeof(video26), video26},
{sizeof(video27), video27},
{sizeof(exit_sleep), exit_sleep},
{sizeof(display_on), display_on},
};
static struct mipi_dsi_cmd nt35510_video_rotate_cmds[] = {
{sizeof(video19_rotate), video19_rotate},
};
int mipi_nt35510_video_wvga_config(void *pdata)
{
int ret = NO_ERROR;
/* 3 Lanes -- Enables Data Lane0, 1, 2 */
unsigned char lane_en = 3;
unsigned long low_pwr_stop_mode = 1;
/* Needed or else will have blank line at top of display */
unsigned char eof_bllp_pwr = 0x9;
unsigned char interleav = 0;
struct lcdc_panel_info *lcdc = NULL;
struct msm_panel_info *pinfo = (struct msm_panel_info *) pdata;
if (pinfo == NULL)
return ERR_INVALID_ARGS;
lcdc = &(pinfo->lcdc);
if (lcdc == NULL)
return ERR_INVALID_ARGS;
ret = mipi_dsi_video_mode_config((pinfo->xres),
(pinfo->yres),
(pinfo->xres),
(pinfo->yres),
(lcdc->h_front_porch),
(lcdc->h_back_porch),
(lcdc->v_front_porch),
(lcdc->v_back_porch),
(lcdc->h_pulse_width),
(lcdc->v_pulse_width),
pinfo->mipi.dst_format,
pinfo->mipi.traffic_mode,
lane_en,
low_pwr_stop_mode,
eof_bllp_pwr,
interleav);
return ret;
}
int mipi_nt35510_video_wvga_on()
{
int ret = NO_ERROR;
return ret;
}
int mipi_nt35510_video_wvga_off()
{
int ret = NO_ERROR;
return ret;
}
int mipi_nt35510_video_wvga_rotate()
{
int ret = NO_ERROR;
ret = mipi_dsi_cmds_tx(nt35510_video_rotate_cmds, ARRAY_SIZE(nt35510_video_rotate_cmds));
return ret;
}
static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
{0x03, 0x01, 0x01, 0x00}, /* regulator */
/* timing */
{0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22,
0x90, 0x18, 0x03, 0x04},
{0x7f, 0x00, 0x00, 0x00}, /* phy ctrl */
{0xbb, 0x02, 0x06, 0x00}, /* strength */
/* pll control */
{0x00, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
0x01, 0x0f, 0x07, /* --> Two lane configuration */
0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
};
void mipi_nt35510_video_wvga_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
pinfo->xres = NT35510_MIPI_FB_WIDTH;
pinfo->yres = NT35510_MIPI_FB_HEIGHT;
pinfo->lcdc.h_back_porch = MIPI_HSYNC_BACK_PORCH_DCLK;
pinfo->lcdc.h_front_porch = MIPI_HSYNC_FRONT_PORCH_DCLK;
pinfo->lcdc.h_pulse_width = MIPI_HSYNC_PULSE_WIDTH;
pinfo->lcdc.v_back_porch = MIPI_VSYNC_BACK_PORCH_LINES;
pinfo->lcdc.v_front_porch = MIPI_VSYNC_FRONT_PORCH_LINES;
pinfo->lcdc.v_pulse_width = MIPI_VSYNC_PULSE_WIDTH;
pinfo->mipi.num_of_lanes = 2;
pinfo->type = MIPI_VIDEO_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->clk_rate = 499000000;
pinfo->mipi.mode = DSI_VIDEO_MODE;
pinfo->mipi.traffic_mode = 2;
pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
pinfo->mipi.tx_eot_append = TRUE;
pinfo->mipi.lane_swap = 1;
pinfo->mipi.panel_cmds = nt35510_panel_video_mode_cmds;
pinfo->mipi.num_of_panel_cmds = \
ARRAY_SIZE(nt35510_panel_video_mode_cmds);
pinfo->on = mipi_nt35510_video_wvga_on;
pinfo->off = mipi_nt35510_video_wvga_off;
pinfo->config = mipi_nt35510_video_wvga_config;
pinfo->rotate = mipi_nt35510_video_wvga_rotate;
return;
}
@@ -0,0 +1,51 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "mipi_renesas.h"
/* Toggle RESET pin of the DSI Client before sending
* panel init commands
*/
int mipi_renesas_panel_dsi_config(int on)
{
if (on) {
gpio_set(128, 0x1);
mdelay(5);
gpio_set(128, 0x0);
gpio_set(129, 0x1);
gpio_config(129, GPIO_OUTPUT);
gpio_set(129, 0x0);
gpio_set(129, 0x1);
mdelay(10);
} else {
gpio_set(128, 0x1);
}
return 0;
}
@@ -0,0 +1,737 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _MIPI_RENESAS_H_
#define _MIPI_RENESAS_H_
#include <stdint.h>
#include <msm_panel.h>
#include <mipi_dsi.h>
#include <sys/types.h>
#include <err.h>
#include <reg.h>
#include <debug.h>
#include <target/display.h>
#include <dev/gpio.h>
/* Renesas Tremelo-M panel: List of commands */
static char config_sleep_out[4] = { 0x11, 0x00, 0x05, 0x80 };
static char config_CMD_MODE[4] = { 0x40, 0x01, 0x15, 0x80 };
static char config_WRTXHT[12] = {
0x07, 0x00, 0x39, 0xC0, 0x92, 0x16, 0x08, 0x08, 0x00, 0x01, 0xe0, 0xff };
static char config_WRTXVT[12] = {
0x07, 0x00, 0x39, 0xC0, 0x8b, 0x02, 0x02, 0x02, 0x00, 0x03, 0x60, 0xff };
static char config_PLL2NR[4] = { 0xa0, 0x24, 0x15, 0x80 };
static char config_PLL2NF1[4] = { 0xa2, 0xd0, 0x15, 0x80 };
static char config_PLL2NF2[4] = { 0xa4, 0x00, 0x15, 0x80 };
static char config_PLL2BWADJ1[4] = { 0xa6, 0xd0, 0x15, 0x80 };
static char config_PLL2BWADJ2[4] = { 0xa8, 0x00, 0x15, 0x80 };
static char config_PLL2CTL[4] = { 0xaa, 0x00, 0x15, 0x80 };
static char config_DBICBR[4] = { 0x48, 0x03, 0x15, 0x80 };
static char config_DBICTYPE[4] = { 0x49, 0x00, 0x15, 0x80 };
static char config_DBICSET1[4] = { 0x4a, 0x1c, 0x15, 0x80 };
static char config_DBICADD[4] = { 0x4b, 0x00, 0x15, 0x80 };
static char config_DBICCTL[4] = { 0x4e, 0x01, 0x15, 0x80 };
/* static char config_COLMOD_565[4] = {0x3a, 0x05, 0x15, 0x80}; */
/* static char config_COLMOD_666PACK[4] = {0x3a, 0x06, 0x15, 0x80}; */
static char config_COLMOD_888[4] = { 0x3a, 0x07, 0x15, 0x80 };
static char config_MADCTL[4] = { 0x36, 0x00, 0x15, 0x80 };
static char config_DBIOC[4] = { 0x82, 0x40, 0x15, 0x80 };
static char config_CASET[12] = {
0x07, 0x00, 0x39, 0xC0, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x01, 0xdf, 0xff };
static char config_PASET[12] = {
0x07, 0x00, 0x39, 0xC0, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5f, 0xff };
static char config_TXON[4] = { 0x81, 0x00, 0x05, 0x80 };
static char config_BLSET_TM[4] = { 0xff, 0x6c, 0x15, 0x80 };
static char config_AGCPSCTL_TM[4] = { 0x56, 0x08, 0x15, 0x80 };
static char config_DBICADD70[4] = { 0x4b, 0x70, 0x15, 0x80 };
static char config_DBICSET_15[4] = { 0x4a, 0x15, 0x15, 0x80 };
static char config_DBICADD72[4] = { 0x4b, 0x72, 0x15, 0x80 };
static char config_Power_Ctrl_2a_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x40, 0x10, 0xff };
static char config_Auto_Sequencer_Setting_a_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char Driver_Output_Ctrl_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x01, 0xff };
static char Driver_Output_Ctrl_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x10, 0xff };
static char config_LCD_drive_AC_Ctrl_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x02, 0xff };
static char config_LCD_drive_AC_Ctrl_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x00, 0xff };
static char config_Entry_Mode_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x03, 0xff };
static char config_Entry_Mode_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char config_Display_Ctrl_1_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x07, 0xff };
static char config_Display_Ctrl_1_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char config_Display_Ctrl_2_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x08, 0xff };
static char config_Display_Ctrl_2_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x04, 0xff };
static char config_Display_Ctrl_3_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x09, 0xff };
static char config_Display_Ctrl_3_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x0c, 0xff };
static char config_Display_IF_Ctrl_1_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x0c, 0xff };
static char config_Display_IF_Ctrl_1_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x40, 0x10, 0xff };
static char config_Display_IF_Ctrl_2_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x0e, 0xff };
static char config_Display_IF_Ctrl_2_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char config_Panel_IF_Ctrl_1_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x20, 0xff };
static char config_Panel_IF_Ctrl_1_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x3f, 0xff };
static char config_Panel_IF_Ctrl_3_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x22, 0xff };
static char config_Panel_IF_Ctrl_3_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x76, 0x00, 0xff };
static char config_Panel_IF_Ctrl_4_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x23, 0xff };
static char config_Panel_IF_Ctrl_4_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x1c, 0x0a, 0xff };
static char config_Panel_IF_Ctrl_5_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x24, 0xff };
static char config_Panel_IF_Ctrl_5_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x1c, 0x2c, 0xff };
static char config_Panel_IF_Ctrl_6_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x25, 0xff };
static char config_Panel_IF_Ctrl_6_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x1c, 0x4e, 0xff };
static char config_Panel_IF_Ctrl_8_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x27, 0xff };
static char config_Panel_IF_Ctrl_8_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char config_Panel_IF_Ctrl_9_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x28, 0xff };
static char config_Panel_IF_Ctrl_9_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x76, 0x0c, 0xff };
static char config_gam_adjust_00_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x00, 0xff };
static char config_gam_adjust_00_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char config_gam_adjust_01_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x01, 0xff };
static char config_gam_adjust_01_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x05, 0x02, 0xff };
static char config_gam_adjust_02_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x02, 0xff };
static char config_gam_adjust_02_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x07, 0x05, 0xff };
static char config_gam_adjust_03_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x03, 0xff };
static char config_gam_adjust_03_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char config_gam_adjust_04_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x04, 0xff };
static char config_gam_adjust_04_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x02, 0x00, 0xff };
static char config_gam_adjust_05_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x05, 0xff };
static char config_gam_adjust_05_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x07, 0x07, 0xff };
static char config_gam_adjust_06_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x06, 0xff };
static char config_gam_adjust_06_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x10, 0x10, 0xff };
static char config_gam_adjust_07_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x07, 0xff };
static char config_gam_adjust_07_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x02, 0x02, 0xff };
static char config_gam_adjust_08_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x08, 0xff };
static char config_gam_adjust_08_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x07, 0x04, 0xff };
static char config_gam_adjust_09_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x09, 0xff };
static char config_gam_adjust_09_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x07, 0x07, 0xff };
static char config_gam_adjust_0A_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x0a, 0xff };
static char config_gam_adjust_0A_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char config_gam_adjust_0B_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x0b, 0xff };
static char config_gam_adjust_0B_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x00, 0xff };
static char config_gam_adjust_0C_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x0c, 0xff };
static char config_gam_adjust_0C_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x07, 0x07, 0xff };
static char config_gam_adjust_0D_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x0d, 0xff };
static char config_gam_adjust_0D_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x10, 0x10, 0xff };
static char config_gam_adjust_10_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x10, 0xff };
static char config_gam_adjust_10_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x04, 0xff };
static char config_gam_adjust_11_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x11, 0xff };
static char config_gam_adjust_11_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x05, 0x03, 0xff };
static char config_gam_adjust_12_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x12, 0xff };
static char config_gam_adjust_12_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x04, 0xff };
static char config_gam_adjust_15_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x15, 0xff };
static char config_gam_adjust_15_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x04, 0xff };
static char config_gam_adjust_16_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x16, 0xff };
static char config_gam_adjust_16_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x1c, 0xff };
static char config_gam_adjust_17_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x17, 0xff };
static char config_gam_adjust_17_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x02, 0x04, 0xff };
static char config_gam_adjust_18_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x18, 0xff };
static char config_gam_adjust_18_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x04, 0x02, 0xff };
static char config_gam_adjust_19_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x19, 0xff };
static char config_gam_adjust_19_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x05, 0xff };
static char config_gam_adjust_1C_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x1c, 0xff };
static char config_gam_adjust_1C_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x07, 0x07, 0xff };
static char config_gam_adjust_1D_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x1D, 0xff };
static char config_gam_adjust_1D_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x02, 0x1f, 0xff };
static char config_gam_adjust_20_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x20, 0xff };
static char config_gam_adjust_20_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x05, 0x07, 0xff };
static char config_gam_adjust_21_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x21, 0xff };
static char config_gam_adjust_21_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x06, 0x04, 0xff };
static char config_gam_adjust_22_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x22, 0xff };
static char config_gam_adjust_22_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x04, 0x05, 0xff };
static char config_gam_adjust_27_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x27, 0xff };
static char config_gam_adjust_27_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x02, 0x03, 0xff };
static char config_gam_adjust_28_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x28, 0xff };
static char config_gam_adjust_28_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x00, 0xff };
static char config_gam_adjust_29_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0x29, 0xff };
static char config_gam_adjust_29_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x02, 0xff };
static char config_Power_Ctrl_1_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x00, 0xff };
static char config_Power_Ctrl_1b_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x36, 0x3c, 0xff };
static char config_Power_Ctrl_2_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x01, 0xff };
static char config_Power_Ctrl_2b_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x40, 0x03, 0xff };
static char config_Power_Ctrl_3_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x02, 0xff };
static char config_Power_Ctrl_3a_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x01, 0xff };
static char config_Power_Ctrl_4_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x03, 0xff };
static char config_Power_Ctrl_4a_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x3c, 0x58, 0xff };
static char config_Power_Ctrl_6_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x0c, 0xff };
static char config_Power_Ctrl_6a_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x35, 0xff };
static char config_Auto_Sequencer_Setting_b_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x02, 0xff };
static char config_Panel_IF_Ctrl_10_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x29, 0xff };
static char config_Panel_IF_Ctrl_10a_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x03, 0xbf, 0xff };
static char config_Auto_Sequencer_Setting_indx[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x01, 0x06, 0xff };
static char config_Auto_Sequencer_Setting_c_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x00, 0x03, 0xff };
static char config_Power_Ctrl_2c_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4c, 0x40, 0x10, 0xff };
static char config_VIDEO[4] = { 0x40, 0x00, 0x15, 0x80 };
static char config_COMMAND[4] = { 0x40, 0x01, 0x15, 0x80 };
static char config_Panel_IF_Ctrl_10_indx_off[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4C, 0x00, 0x29, 0xff };
static char config_Panel_IF_Ctrl_10b_cmd_off[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4C, 0x00, 0x02, 0xff };
static char config_Power_Ctrl_1a_cmd[8] = {
0x03, 0x00, 0x39, 0xC0, 0x4C, 0x30, 0x00, 0xff };
static struct mipi_dsi_cmd renesas_panel_video_mode_cmds[] = {
{sizeof(config_sleep_out), config_sleep_out},
{sizeof(config_CMD_MODE), config_CMD_MODE},
{sizeof(config_WRTXHT), config_WRTXHT},
{sizeof(config_WRTXVT), config_WRTXVT},
{sizeof(config_PLL2NR), config_PLL2NR},
{sizeof(config_PLL2NF1), config_PLL2NF1},
{sizeof(config_PLL2NF2), config_PLL2NF2},
{sizeof(config_PLL2BWADJ1), config_PLL2BWADJ1},
{sizeof(config_PLL2BWADJ2), config_PLL2BWADJ2},
{sizeof(config_PLL2CTL), config_PLL2CTL},
{sizeof(config_DBICBR), config_DBICBR},
{sizeof(config_DBICTYPE), config_DBICTYPE},
{sizeof(config_DBICSET1), config_DBICSET1},
{sizeof(config_DBICADD), config_DBICADD},
{sizeof(config_DBICCTL), config_DBICCTL},
{sizeof(config_COLMOD_888), config_COLMOD_888},
/* Choose config_COLMOD_565 or config_COLMOD_666PACK for other modes */
{sizeof(config_MADCTL), config_MADCTL},
{sizeof(config_DBIOC), config_DBIOC},
{sizeof(config_CASET), config_CASET},
{sizeof(config_PASET), config_PASET},
{sizeof(config_TXON), config_TXON},
{sizeof(config_BLSET_TM), config_BLSET_TM},
{sizeof(config_AGCPSCTL_TM), config_AGCPSCTL_TM},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Power_Ctrl_1_indx), config_Power_Ctrl_1_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Power_Ctrl_1a_cmd), config_Power_Ctrl_1a_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Power_Ctrl_2_indx), config_Power_Ctrl_2_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Power_Ctrl_2a_cmd), config_Power_Ctrl_2a_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Auto_Sequencer_Setting_indx),
config_Auto_Sequencer_Setting_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Auto_Sequencer_Setting_a_cmd),
config_Auto_Sequencer_Setting_a_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(Driver_Output_Ctrl_indx), Driver_Output_Ctrl_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(Driver_Output_Ctrl_cmd),
Driver_Output_Ctrl_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_LCD_drive_AC_Ctrl_indx),
config_LCD_drive_AC_Ctrl_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_LCD_drive_AC_Ctrl_cmd),
config_LCD_drive_AC_Ctrl_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Entry_Mode_indx),
config_Entry_Mode_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Entry_Mode_cmd),
config_Entry_Mode_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Display_Ctrl_1_indx),
config_Display_Ctrl_1_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Display_Ctrl_1_cmd),
config_Display_Ctrl_1_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Display_Ctrl_2_indx),
config_Display_Ctrl_2_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Display_Ctrl_2_cmd),
config_Display_Ctrl_2_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Display_Ctrl_3_indx),
config_Display_Ctrl_3_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Display_Ctrl_3_cmd),
config_Display_Ctrl_3_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Display_IF_Ctrl_1_indx),
config_Display_IF_Ctrl_1_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Display_IF_Ctrl_1_cmd),
config_Display_IF_Ctrl_1_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Display_IF_Ctrl_2_indx),
config_Display_IF_Ctrl_2_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Display_IF_Ctrl_2_cmd),
config_Display_IF_Ctrl_2_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Panel_IF_Ctrl_1_indx),
config_Panel_IF_Ctrl_1_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Panel_IF_Ctrl_1_cmd),
config_Panel_IF_Ctrl_1_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Panel_IF_Ctrl_3_indx),
config_Panel_IF_Ctrl_3_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Panel_IF_Ctrl_3_cmd),
config_Panel_IF_Ctrl_3_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Panel_IF_Ctrl_4_indx),
config_Panel_IF_Ctrl_4_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Panel_IF_Ctrl_4_cmd),
config_Panel_IF_Ctrl_4_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Panel_IF_Ctrl_5_indx),
config_Panel_IF_Ctrl_5_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Panel_IF_Ctrl_5_cmd),
config_Panel_IF_Ctrl_5_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Panel_IF_Ctrl_6_indx),
config_Panel_IF_Ctrl_6_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Panel_IF_Ctrl_6_cmd),
config_Panel_IF_Ctrl_6_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Panel_IF_Ctrl_8_indx),
config_Panel_IF_Ctrl_8_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Panel_IF_Ctrl_8_cmd),
config_Panel_IF_Ctrl_8_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Panel_IF_Ctrl_9_indx),
config_Panel_IF_Ctrl_9_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Panel_IF_Ctrl_9_cmd),
config_Panel_IF_Ctrl_9_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_00_indx),
config_gam_adjust_00_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_00_cmd),
config_gam_adjust_00_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_01_indx),
config_gam_adjust_01_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_01_cmd),
config_gam_adjust_01_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_02_indx),
config_gam_adjust_02_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_02_cmd),
config_gam_adjust_02_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_03_indx),
config_gam_adjust_03_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_03_cmd),
config_gam_adjust_03_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_04_indx), config_gam_adjust_04_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_04_cmd), config_gam_adjust_04_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_05_indx), config_gam_adjust_05_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_05_cmd), config_gam_adjust_05_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_06_indx), config_gam_adjust_06_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_06_cmd), config_gam_adjust_06_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_07_indx), config_gam_adjust_07_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_07_cmd), config_gam_adjust_07_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_08_indx), config_gam_adjust_08_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_08_cmd), config_gam_adjust_08_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_09_indx), config_gam_adjust_09_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_09_cmd), config_gam_adjust_09_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_0A_indx), config_gam_adjust_0A_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_0A_cmd), config_gam_adjust_0A_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_0B_indx), config_gam_adjust_0B_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_0B_cmd), config_gam_adjust_0B_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_0C_indx), config_gam_adjust_0C_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_0C_cmd), config_gam_adjust_0C_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_0D_indx), config_gam_adjust_0D_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_0D_cmd), config_gam_adjust_0D_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_10_indx), config_gam_adjust_10_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_10_cmd), config_gam_adjust_10_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_11_indx), config_gam_adjust_11_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_11_cmd), config_gam_adjust_11_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_12_indx), config_gam_adjust_12_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_12_cmd), config_gam_adjust_12_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_15_indx), config_gam_adjust_15_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_15_cmd), config_gam_adjust_15_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_16_indx), config_gam_adjust_16_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_16_cmd), config_gam_adjust_16_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_17_indx), config_gam_adjust_17_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_17_cmd), config_gam_adjust_17_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_18_indx), config_gam_adjust_18_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_18_cmd), config_gam_adjust_18_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_19_indx), config_gam_adjust_19_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_19_cmd), config_gam_adjust_19_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_1C_indx), config_gam_adjust_1C_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_1C_cmd), config_gam_adjust_1C_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_1D_indx), config_gam_adjust_1D_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_1D_cmd), config_gam_adjust_1D_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_20_indx), config_gam_adjust_20_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_20_cmd), config_gam_adjust_20_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_21_indx), config_gam_adjust_21_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_21_cmd), config_gam_adjust_21_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_22_indx), config_gam_adjust_22_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_22_cmd), config_gam_adjust_22_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_27_indx), config_gam_adjust_27_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_27_cmd), config_gam_adjust_27_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_28_indx), config_gam_adjust_28_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_28_cmd), config_gam_adjust_28_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_gam_adjust_29_indx), config_gam_adjust_29_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_gam_adjust_29_cmd), config_gam_adjust_29_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Power_Ctrl_1_indx), config_Power_Ctrl_1_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Power_Ctrl_1b_cmd), config_Power_Ctrl_1b_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Power_Ctrl_2_indx), config_Power_Ctrl_2_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Power_Ctrl_2b_cmd), config_Power_Ctrl_2b_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Power_Ctrl_3_indx), config_Power_Ctrl_3_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Power_Ctrl_3a_cmd), config_Power_Ctrl_3a_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Power_Ctrl_4_indx), config_Power_Ctrl_4_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Power_Ctrl_4a_cmd), config_Power_Ctrl_4a_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Power_Ctrl_6_indx), config_Power_Ctrl_6_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Power_Ctrl_6a_cmd), config_Power_Ctrl_6a_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Auto_Sequencer_Setting_indx),
config_Auto_Sequencer_Setting_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Auto_Sequencer_Setting_b_cmd),
config_Auto_Sequencer_Setting_b_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Panel_IF_Ctrl_10_indx),
config_Panel_IF_Ctrl_10_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Panel_IF_Ctrl_10a_cmd),
config_Panel_IF_Ctrl_10a_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Auto_Sequencer_Setting_indx),
config_Auto_Sequencer_Setting_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Auto_Sequencer_Setting_c_cmd),
config_Auto_Sequencer_Setting_c_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD70), config_DBICADD70},
{sizeof(config_Power_Ctrl_2_indx),
config_Power_Ctrl_2_indx},
{sizeof(config_DBICSET_15), config_DBICSET_15},
{sizeof(config_DBICADD72), config_DBICADD72},
{sizeof(config_Power_Ctrl_2c_cmd),
config_Power_Ctrl_2c_cmd},
{sizeof(config_DBICSET_15), config_DBICSET_15},
/* Change this command to config_VIDEO for video mode */
{sizeof(config_COMMAND), config_COMMAND},
};
/* Toggle RESET pin of the DSI Client before sending
* panel init commands
*/
int mipi_renesas_panel_dsi_config(int on);
#endif /* _MIPI_RENESAS_H_ */
@@ -0,0 +1,135 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "mipi_renesas.h"
int mipi_renesas_cmd_fwvga_config(void *pdata)
{
int ret = NO_ERROR;
struct msm_panel_info *pinfo = (struct msm_panel_info *) pdata;
if (pinfo == NULL)
return ERR_INVALID_ARGS;
ret = mipi_dsi_cmd_mode_config((pinfo->xres),
(pinfo->yres),
(pinfo->xres),
(pinfo->yres),
pinfo->mipi.dst_format,
pinfo->mipi.traffic_mode);
return ret;
}
int mipi_renesas_cmd_fwvga_on()
{
int ret = NO_ERROR;
return ret;
}
int mipi_renesas_cmd_fwvga_off()
{
int ret = NO_ERROR;
return ret;
}
static struct mipi_dsi_phy_ctrl dsi_cmd_mode_phy_db = {
/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
{0x03, 0x01, 0x01, 0x00}, /* regulator */
/* timing */
{0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22,
0x90, 0x18, 0x03, 0x04},
{0x7f, 0x00, 0x00, 0x00}, /* phy ctrl */
{0xbb, 0x02, 0x06, 0x00}, /* strength */
/* pll control */
{0x00, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
0x01, 0x0f, 0x07, /* --> Two lane configuration */
0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
};
void mipi_renesas_cmd_fwvga_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
pinfo->xres = REN_MIPI_FB_WIDTH;
pinfo->yres = REN_MIPI_FB_HEIGHT;
pinfo->mipi.num_of_lanes = 2;
pinfo->type = MIPI_CMD_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->mipi.mode = DSI_CMD_MODE;
pinfo->mipi.traffic_mode = 0;
pinfo->mipi.dst_format = 0;
pinfo->mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
pinfo->mipi.tx_eot_append = TRUE;
pinfo->mipi.lane_swap = 1;
pinfo->mipi.panel_cmds = renesas_panel_video_mode_cmds;
pinfo->mipi.num_of_panel_cmds = ARRAY_SIZE(renesas_panel_video_mode_cmds);
pinfo->on = mipi_renesas_cmd_fwvga_on;
pinfo->off = mipi_renesas_cmd_fwvga_off;
pinfo->config = mipi_renesas_cmd_fwvga_config;
return;
}
void mipi_renesas_cmd_hvga_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
pinfo->xres = REN_MIPI_FB_WIDTH_HVGA;
pinfo->yres = REN_MIPI_FB_HEIGHT_HVGA;
pinfo->mipi.num_of_lanes = 1;
pinfo->type = MIPI_CMD_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->clk_rate = 499000000;
pinfo->mipi.mode = DSI_CMD_MODE;
pinfo->mipi.traffic_mode = 0;
pinfo->mipi.dst_format = 0;
pinfo->mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
pinfo->mipi.tx_eot_append = TRUE;
pinfo->mipi.lane_swap = 1;
pinfo->mipi.panel_cmds = renesas_panel_video_mode_cmds;
pinfo->mipi.num_of_panel_cmds = ARRAY_SIZE(renesas_panel_video_mode_cmds);
pinfo->on = mipi_renesas_cmd_fwvga_on;
pinfo->off = mipi_renesas_cmd_fwvga_off;
pinfo->config = mipi_renesas_cmd_fwvga_config;
return;
}
@@ -0,0 +1,169 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "mipi_renesas.h"
int mipi_renesas_video_fwvga_config(void *pdata)
{
int ret = NO_ERROR;
/* 3 Lanes -- Enables Data Lane0, 1, 2 */
unsigned char lane_en = 3;
unsigned long low_pwr_stop_mode = 1;
/* Needed or else will have blank line at top of display */
unsigned char eof_bllp_pwr = 0x9;
unsigned char interleav = 0;
struct lcdc_panel_info *lcdc = NULL;
struct msm_panel_info *pinfo = (struct msm_panel_info *) pdata;
if (pinfo == NULL)
return ERR_INVALID_ARGS;
lcdc = &(pinfo->lcdc);
if (lcdc == NULL)
return ERR_INVALID_ARGS;
ret = mipi_dsi_video_mode_config((pinfo->xres),
(pinfo->yres),
(pinfo->xres),
(pinfo->yres),
(lcdc->h_front_porch),
(lcdc->h_back_porch),
(lcdc->v_front_porch),
(lcdc->v_back_porch),
(lcdc->h_pulse_width),
(lcdc->v_pulse_width),
pinfo->mipi.dst_format,
pinfo->mipi.traffic_mode,
lane_en,
low_pwr_stop_mode,
eof_bllp_pwr,
interleav);
return ret;
}
int mipi_renesas_video_fwvga_on()
{
int ret = NO_ERROR;
return ret;
}
int mipi_renesas_video_fwvga_off()
{
int ret = NO_ERROR;
return ret;
}
static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
{0x03, 0x01, 0x01, 0x00}, /* regulator */
/* timing */
{0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22,
0x90, 0x18, 0x03, 0x04},
{0x7f, 0x00, 0x00, 0x00}, /* phy ctrl */
{0xbb, 0x02, 0x06, 0x00}, /* strength */
/* pll control */
{0x00, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
0x01, 0x0f, 0x07, /* --> Two lane configuration */
0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
};
void mipi_renesas_video_fwvga_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
pinfo->xres = REN_MIPI_FB_WIDTH;
pinfo->yres = REN_MIPI_FB_HEIGHT;
pinfo->lcdc.h_back_porch = MIPI_HSYNC_BACK_PORCH_DCLK;
pinfo->lcdc.h_front_porch = MIPI_HSYNC_FRONT_PORCH_DCLK;
pinfo->lcdc.h_pulse_width = MIPI_HSYNC_PULSE_WIDTH;
pinfo->lcdc.v_back_porch = MIPI_VSYNC_BACK_PORCH_LINES;
pinfo->lcdc.v_front_porch = MIPI_VSYNC_FRONT_PORCH_LINES;
pinfo->lcdc.v_pulse_width = MIPI_VSYNC_PULSE_WIDTH;
pinfo->mipi.num_of_lanes = 2;
pinfo->type = MIPI_VIDEO_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->clk_rate = 499000000;
pinfo->mipi.mode = DSI_VIDEO_MODE;
pinfo->mipi.traffic_mode = 2;
pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
pinfo->mipi.tx_eot_append = TRUE;
pinfo->mipi.lane_swap = 1;
pinfo->mipi.panel_cmds = renesas_panel_video_mode_cmds;
pinfo->mipi.num_of_panel_cmds = ARRAY_SIZE(renesas_panel_video_mode_cmds);
pinfo->on = mipi_renesas_video_fwvga_on;
pinfo->off = mipi_renesas_video_fwvga_off;
pinfo->config = mipi_renesas_video_fwvga_config;
return;
}
void mipi_renesas_video_hvga_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
pinfo->xres = REN_MIPI_FB_WIDTH_HVGA;
pinfo->yres = REN_MIPI_FB_HEIGHT_HVGA;
pinfo->lcdc.h_front_porch = MIPI_HSYNC_FRONT_PORCH_DCLK_HVGA;
pinfo->lcdc.h_back_porch = MIPI_HSYNC_BACK_PORCH_DCLK_HVGA;
pinfo->lcdc.v_front_porch = MIPI_VSYNC_FRONT_PORCH_LINES_HVGA;
pinfo->lcdc.v_back_porch = MIPI_VSYNC_BACK_PORCH_LINES_HVGA;
pinfo->lcdc.h_pulse_width = MIPI_HSYNC_PULSE_WIDTH_HVGA;
pinfo->lcdc.v_pulse_width = MIPI_VSYNC_PULSE_WIDTH_HVGA;
pinfo->mipi.num_of_lanes = 1;
pinfo->type = MIPI_VIDEO_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->mipi.mode = DSI_VIDEO_MODE;
pinfo->mipi.traffic_mode = 2;
pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
pinfo->mipi.tx_eot_append = TRUE;
pinfo->mipi.lane_swap = 1;
pinfo->mipi.panel_cmds = renesas_panel_video_mode_cmds;
pinfo->mipi.num_of_panel_cmds = ARRAY_SIZE(renesas_panel_video_mode_cmds);
pinfo->on = mipi_renesas_video_fwvga_on;
pinfo->off = mipi_renesas_video_fwvga_off;
pinfo->config = mipi_renesas_video_fwvga_config;
return;
}
@@ -0,0 +1,163 @@
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <msm_panel.h>
#include <mipi_dsi.h>
#include <sys/types.h>
#include <err.h>
#include <reg.h>
#include <mdp4.h>
int mipi_sharp_video_qhd_config(void *pdata)
{
int ret = NO_ERROR;
/* 2 Lanes -- Enables Data Lane0, 1 */
uint8_t lane_en = 0x3;
uint64_t low_pwr_stop_mode = 0;
/* Needed or else will have blank line at top of display */
uint8_t eof_bllp_pwr = 0x9;
uint8_t interleav = 0;
struct lcdc_panel_info *lcdc = NULL;
struct msm_panel_info *pinfo = (struct msm_panel_info *)pdata;
if (!pinfo)
return ERR_INVALID_ARGS;
lcdc = &(pinfo->lcdc);
if (!lcdc)
return ERR_INVALID_ARGS;
ret = mipi_dsi_video_mode_config((pinfo->xres + lcdc->xres_pad),
(pinfo->yres + lcdc->yres_pad),
(pinfo->xres),
(pinfo->yres),
(lcdc->h_front_porch),
(lcdc->h_back_porch + lcdc->h_pulse_width),
(lcdc->v_front_porch),
(lcdc->v_back_porch + lcdc->v_pulse_width),
(lcdc->h_pulse_width),
(lcdc->v_pulse_width),
pinfo->mipi.dst_format,
pinfo->mipi.traffic_mode,
lane_en,
low_pwr_stop_mode,
eof_bllp_pwr,
interleav);
return ret;
}
int mipi_sharp_video_qhd_on()
{
return NO_ERROR;
}
int mipi_sharp_video_qhd_off()
{
return NO_ERROR;
}
static struct mdss_dsi_phy_ctrl dsi_video_mode_phy_db = {
/* 540x960, RGB888, 2 Lane 60 fps video mode */
/* regulator */
{0x07, 0x09, 0x03, 0x00, 0x20, 0x00, 0x01},
/* timing */
{0x46, 0x1d, 0x20, 0x00, 0x39, 0x3a, 0x21, 0x21,
0x32, 0x03, 0x04, 0x00},
/* phy ctrl */
{0x5f, 0x00, 0x00, 0x10},
/* strength */
{0xff, 0x06},
/* bist control */
{0x00, 0x00, 0xb1, 0xff, 0x00, 0x00},
/* lanes config */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x97,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x97,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x97,
0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x97,
0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xbb},
};
void mipi_sharp_video_qhd_init(struct msm_panel_info *pinfo)
{
if (!pinfo)
return;
pinfo->xres = 540;
pinfo->yres = 960;
pinfo->type = MIPI_VIDEO_PANEL;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->lcdc.h_back_porch = 80;
pinfo->lcdc.h_front_porch = 48;
pinfo->lcdc.h_pulse_width = 32;
pinfo->lcdc.v_back_porch = 15;
pinfo->lcdc.v_front_porch = 3;
pinfo->lcdc.v_pulse_width = 10;
pinfo->lcdc.border_clr = 0; /* blk */
pinfo->lcdc.underflow_clr = 0xff; /* blue */
pinfo->lcdc.hsync_skew = 0;
pinfo->clk_rate = 500000000;
pinfo->mipi.mode = DSI_VIDEO_MODE;
pinfo->mipi.pulse_mode_hsa_he = FALSE;
pinfo->mipi.hfp_power_stop = FALSE;
pinfo->mipi.hbp_power_stop = FALSE;
pinfo->mipi.hsa_power_stop = FALSE;
pinfo->mipi.eof_bllp_power_stop = FALSE;
pinfo->mipi.bllp_power_stop = FALSE;
pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
pinfo->mipi.vc = 0;
pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
pinfo->mipi.data_lane0 = TRUE;
pinfo->mipi.data_lane1 = TRUE;
pinfo->mipi.data_lane2 = FALSE;
pinfo->mipi.data_lane3 = FALSE;
pinfo->mipi.t_clk_post = 0x04;
pinfo->mipi.t_clk_pre = 0x1c;
pinfo->mipi.stream = 0; /* dma_p */
pinfo->mipi.mdp_trigger = 0;
pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
pinfo->mipi.frame_rate = 60;
pinfo->mipi.mdss_dsi_phy_db = &dsi_video_mode_phy_db;
pinfo->mipi.tx_eot_append = TRUE;
pinfo->mipi.num_of_lanes = 2;
pinfo->mipi.panel_cmds = sharp_qhd_video_mode_cmds;
pinfo->mipi.num_of_panel_cmds =
ARRAY_SIZE(sharp_qhd_video_mode_cmds);
pinfo->on = mipi_sharp_video_qhd_on;
pinfo->off = mipi_sharp_video_qhd_off;
pinfo->config = mipi_sharp_video_qhd_config;
}

Some files were not shown because too many files have changed in this diff Show More