mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-01-01 18:11:10 +02:00
use interrupt controller
This commit is contained in:
parent
7c5ea99cba
commit
c2dbe6e1e9
@ -41,12 +41,12 @@ unsigned raw_zalloc ():
|
|||||||
FreePage *ret = zero_pages
|
FreePage *ret = zero_pages
|
||||||
if !ret:
|
if !ret:
|
||||||
ret = junk_pages
|
ret = junk_pages
|
||||||
for unsigned i = 1; i < (PAGE_SIZE >> 2); ++i:
|
|
||||||
((unsigned *)ret)[i] = 0
|
|
||||||
junk_pages = ret->next
|
junk_pages = ret->next
|
||||||
|
for unsigned i = 0; i < (PAGE_SIZE >> 2); ++i:
|
||||||
|
((unsigned *)ret)[i] = 0
|
||||||
else:
|
else:
|
||||||
zero_pages = ret->next
|
zero_pages = ret->next
|
||||||
ret->next = NULL
|
ret->next = NULL
|
||||||
return (unsigned)ret
|
return (unsigned)ret
|
||||||
|
|
||||||
void raw_pfree (unsigned page):
|
void raw_pfree (unsigned page):
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#ifndef _KERNEL_HH
|
#ifndef _KERNEL_HH
|
||||||
#define _KERNEL_HH
|
#define _KERNEL_HH
|
||||||
|
|
||||||
|
// Number of clock interrupts per second.
|
||||||
|
#define HZ 10
|
||||||
|
|
||||||
// Include definitions which are shared with user space.
|
// Include definitions which are shared with user space.
|
||||||
#define __KERNEL
|
#define __KERNEL
|
||||||
#include "iris.h"
|
#include "iris.h"
|
||||||
@ -207,7 +210,6 @@ bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write)
|
|||||||
void Memory_arch_unmap (Memory *mem, Page *page, unsigned address)
|
void Memory_arch_unmap (Memory *mem, Page *page, unsigned address)
|
||||||
Page *Memory_arch_get_mapping (Memory *mem, unsigned address, bool *writable)
|
Page *Memory_arch_get_mapping (Memory *mem, unsigned address, bool *writable)
|
||||||
void Page_arch_update_mapping (Page *page)
|
void Page_arch_update_mapping (Page *page)
|
||||||
void arch_invoke ()
|
|
||||||
void arch_register_interrupt (unsigned num, Receiver *r)
|
void arch_register_interrupt (unsigned num, Receiver *r)
|
||||||
|
|
||||||
bool Memory::map (Page *page, unsigned address, bool write):
|
bool Memory::map (Page *page, unsigned address, bool write):
|
||||||
|
@ -132,17 +132,6 @@ void Memory_arch_init (Memory *mem):
|
|||||||
mem->arch.directory = NULL
|
mem->arch.directory = NULL
|
||||||
mem->arch.shadow = NULL
|
mem->arch.shadow = NULL
|
||||||
|
|
||||||
static void flush_tlb (unsigned asid):
|
|
||||||
for unsigned tlb = 1; tlb < 32; ++tlb:
|
|
||||||
cp0_set (CP0_INDEX, tlb)
|
|
||||||
__asm__ volatile ("tlbr")
|
|
||||||
unsigned hi
|
|
||||||
cp0_get (CP0_ENTRY_HI, hi)
|
|
||||||
if (hi & 0x1f) == asid:
|
|
||||||
// Set asid to 0, which is only used by the idle task.
|
|
||||||
cp0_set (CP0_ENTRY_HI, 0x2000 * tlb)
|
|
||||||
__asm__ volatile ("tlbwi")
|
|
||||||
|
|
||||||
void Memory_arch_free (Memory *mem):
|
void Memory_arch_free (Memory *mem):
|
||||||
while mem->arch.first_page_table:
|
while mem->arch.first_page_table:
|
||||||
mem->unmap (mem->arch.first_page_table->first_page->page, mem->arch.first_page_table->first_page->mapping)
|
mem->unmap (mem->arch.first_page_table->first_page->page, mem->arch.first_page_table->first_page->mapping)
|
||||||
@ -322,61 +311,6 @@ void Page_arch_update_mapping (Page *page):
|
|||||||
as->arch.directory[de][te] = t
|
as->arch.directory[de][te] = t
|
||||||
tlb_reset (p->mapping & ~1, as->arch.asid, t)
|
tlb_reset (p->mapping & ~1, as->arch.asid, t)
|
||||||
|
|
||||||
void arch_invoke ():
|
|
||||||
Capability *target
|
|
||||||
bool wait
|
|
||||||
Thread *caller = current
|
|
||||||
target = caller->address_space->find_capability (caller->arch.v0, &wait)
|
|
||||||
if !target:
|
|
||||||
// TODO: there must be no action here. This is just because the rest doesn't work yet.
|
|
||||||
dbg_send (3, 2)
|
|
||||||
//dbg_send (caller->arch.v0)
|
|
||||||
schedule ()
|
|
||||||
// Calling an invalid capability always fails.
|
|
||||||
caller->arch.v0 = 0
|
|
||||||
else:
|
|
||||||
if wait:
|
|
||||||
caller->wait ()
|
|
||||||
Capability::Context c
|
|
||||||
c.cap[0] = caller->address_space->find_capability (caller->arch.a0, &c.copy[0])
|
|
||||||
c.cap[1] = caller->address_space->find_capability (caller->arch.a1, &c.copy[1])
|
|
||||||
c.cap[2] = caller->address_space->find_capability (caller->arch.a2, &c.copy[2])
|
|
||||||
c.cap[3] = caller->address_space->find_capability (caller->arch.a3, &c.copy[3])
|
|
||||||
c.data[0] = caller->arch.t0
|
|
||||||
c.data[1] = caller->arch.t1
|
|
||||||
c.data[2] = caller->arch.t2
|
|
||||||
c.data[3] = caller->arch.t3
|
|
||||||
caller->arch.v0 = target->invoke (&c) ? 1 : 0
|
|
||||||
if !current:
|
|
||||||
if caller != &idle && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
|
|
||||||
current = caller
|
|
||||||
else:
|
|
||||||
schedule ()
|
|
||||||
if !current:
|
|
||||||
current = &idle
|
|
||||||
if caller != current:
|
|
||||||
if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
|
|
||||||
if asids[0]:
|
|
||||||
current->address_space->arch.asid = asids[0]
|
|
||||||
asids[0] = asids[asids[0]]
|
|
||||||
else:
|
|
||||||
static unsigned random = 1
|
|
||||||
current->address_space->arch.asid = random
|
|
||||||
// Overwrite used asid, so flush those values from tlb.
|
|
||||||
flush_tlb (random)
|
|
||||||
++random
|
|
||||||
if random >= 64:
|
|
||||||
random = 1
|
|
||||||
asids[current->address_space->arch.asid] = (unsigned)current->address_space
|
|
||||||
cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid)
|
|
||||||
directory = current->address_space->arch.directory
|
|
||||||
unsigned status
|
|
||||||
cp0_get (CP0_STATUS, status)
|
|
||||||
status &= 0x0fffffff
|
|
||||||
if current->flags & THREAD_FLAG_PRIV:
|
|
||||||
status |= 0x10000000
|
|
||||||
cp0_set (CP0_STATUS, status | 0x13)
|
|
||||||
|
|
||||||
void arch_register_interrupt (unsigned num, Receiver *r):
|
void arch_register_interrupt (unsigned num, Receiver *r):
|
||||||
arch_interrupt_receiver[num] = r
|
arch_interrupt_receiver[num] = r
|
||||||
unsigned status
|
unsigned status
|
||||||
|
@ -106,6 +106,8 @@
|
|||||||
|
|
||||||
#ifndef ASM
|
#ifndef ASM
|
||||||
|
|
||||||
|
void flush_tlb (unsigned asid)
|
||||||
|
|
||||||
struct Thread_arch:
|
struct Thread_arch:
|
||||||
unsigned at, v0, v1, a0, a1, a2, a3
|
unsigned at, v0, v1, a0, a1, a2, a3
|
||||||
unsigned t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
|
unsigned t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
|
||||||
@ -140,7 +142,7 @@ struct Memory_arch:
|
|||||||
// Pointers to Memory when asid is taken, index of next free, or 0, if free.
|
// Pointers to Memory when asid is taken, index of next free, or 0, if free.
|
||||||
// asid[0] is used as index to first free asid.
|
// asid[0] is used as index to first free asid.
|
||||||
EXTERN unsigned asids[64]
|
EXTERN unsigned asids[64]
|
||||||
EXTERN Receiver *arch_interrupt_receiver[8]
|
EXTERN Receiver *arch_interrupt_receiver[32]
|
||||||
|
|
||||||
// Functions which can be called from assembly must not be mangled.
|
// Functions which can be called from assembly must not be mangled.
|
||||||
extern "C":
|
extern "C":
|
||||||
|
@ -207,7 +207,7 @@ void init ():
|
|||||||
junk_pages = (FreePage *)(((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK)
|
junk_pages = (FreePage *)(((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK)
|
||||||
FreePage *p, *next
|
FreePage *p, *next
|
||||||
unsigned count = 1
|
unsigned count = 1
|
||||||
for p = junk_pages, next = p; (unsigned)next - 0x80000000 < (1 << 27); p = next, next = (FreePage *)((unsigned)p + ~PAGE_MASK + 1):
|
for p = junk_pages, next = p; (unsigned)next - 0x80000000 < (1 << 27); p = next, next = (FreePage *)((unsigned)p + PAGE_SIZE):
|
||||||
p->next = next
|
p->next = next
|
||||||
++count
|
++count
|
||||||
p->next = NULL
|
p->next = NULL
|
||||||
@ -228,15 +228,47 @@ void init ():
|
|||||||
top_memory.arch.directory = NULL
|
top_memory.arch.directory = NULL
|
||||||
top_memory.arch.asid = 0
|
top_memory.arch.asid = 0
|
||||||
|
|
||||||
|
// Record all asids as unused.
|
||||||
for unsigned i = 0; i < 63; ++i:
|
for unsigned i = 0; i < 63; ++i:
|
||||||
asids[i] = i + 1
|
asids[i] = i + 1
|
||||||
asids[63] = 0
|
asids[63] = 0
|
||||||
|
|
||||||
|
// Set up initial threads.
|
||||||
init_threads ()
|
init_threads ()
|
||||||
|
|
||||||
// Say we're handling an exception. Don't enable interrupts; this will happen when handlers are registered.
|
// Set up the rest of the hardware (copied from Linux).
|
||||||
// Since we're going to enter the idle task, allow access to cp0.
|
cpm_idle_mode ()
|
||||||
cp0_set (CP0_STATUS, 0x10000013)
|
cpm_enable_cko1 ()
|
||||||
|
cpm_start_all ()
|
||||||
|
harb_set_priority (0x08)
|
||||||
|
dmac_enable_all_channels ()
|
||||||
|
harb_usb0_uhc ()
|
||||||
|
gpio_as_emc ()
|
||||||
|
gpio_as_uart0 ()
|
||||||
|
gpio_as_dma ()
|
||||||
|
gpio_as_eth ()
|
||||||
|
gpio_as_usb ()
|
||||||
|
gpio_as_lcd_master ()
|
||||||
|
gpio_as_msc ()
|
||||||
|
GPIO_GPDIR (GPIO_PWM0_PORT) |= 1 << GPIO_PWM0
|
||||||
|
GPIO_GPDR (GPIO_PWM0_PORT) |= 1 << GPIO_PWM0
|
||||||
|
GPIO_GPDIR (GPIO_USB_CLK_EN_PORT) |= 1 << GPIO_USB_CLK_EN
|
||||||
|
GPIO_GPDR (GPIO_USB_CLK_EN_PORT) |= 1 << GPIO_USB_CLK_EN
|
||||||
|
|
||||||
|
// Start the operating system timer.
|
||||||
|
unsigned latch = (JZ_EXTAL + (HZ>>1)) / HZ
|
||||||
|
ost_set_mode (0, OST_TCSR_UIE | OST_TCSR_CKS_EXTAL)
|
||||||
|
ost_set_reload (0, latch)
|
||||||
|
ost_set_count (0, latch)
|
||||||
|
ost_enable_channel (0)
|
||||||
|
|
||||||
|
// Unset all interrupt handlers.
|
||||||
|
for unsigned i = 0; i < 32; ++i:
|
||||||
|
arch_interrupt_receiver[i] = NULL
|
||||||
|
|
||||||
|
// Say we're handling an exception. Since we're going to enter the idle task, allow access to cp0.
|
||||||
|
// All interrupts enter the CPU through the interrupt controller at IP2, so enable that.
|
||||||
|
cp0_set (CP0_STATUS, 0x10000413)
|
||||||
|
|
||||||
// Done; return to user space (the idle task).
|
// Done; return to user space (the idle task).
|
||||||
__asm__ volatile ("eret")
|
__asm__ volatile ("eret")
|
||||||
|
@ -43,16 +43,16 @@ Thread *tlb_refill ():
|
|||||||
__asm__ volatile ("tlbwr")
|
__asm__ volatile ("tlbwr")
|
||||||
return current
|
return current
|
||||||
|
|
||||||
|
static void timer_interrupt ():
|
||||||
|
|
||||||
/// An interrupt which is not an exception has occurred.
|
/// An interrupt which is not an exception has occurred.
|
||||||
Thread *interrupt ():
|
Thread *interrupt ():
|
||||||
panic (0x88877722, "Interrupt")
|
panic (0x88877722, "Interrupt")
|
||||||
unsigned cause, status
|
unsigned ipr = INTC_IPR
|
||||||
cp0_get (CP0_CAUSE, cause)
|
for unsigned i = 1; i < 32; ++i:
|
||||||
cp0_get (CP0_STATUS, status)
|
if ipr & (1 << i):
|
||||||
for unsigned i = 0; i < 8; ++i:
|
|
||||||
if cause & (1 << (i + 8)):
|
|
||||||
// Disable the interrupt while handling it.
|
// Disable the interrupt while handling it.
|
||||||
status &= ~(1 << (i + 8))
|
intc_mask_irq (i)
|
||||||
// Send message to interrupt handler.
|
// Send message to interrupt handler.
|
||||||
if arch_interrupt_receiver[i]:
|
if arch_interrupt_receiver[i]:
|
||||||
Capability::Context c
|
Capability::Context c
|
||||||
@ -61,8 +61,78 @@ Thread *interrupt ():
|
|||||||
c.cap[j] = NULL
|
c.cap[j] = NULL
|
||||||
c.copy[j] = false
|
c.copy[j] = false
|
||||||
arch_interrupt_receiver[i]->send_message (i, &c)
|
arch_interrupt_receiver[i]->send_message (i, &c)
|
||||||
|
if ipr & 1:
|
||||||
|
ost_clear_uf (0)
|
||||||
|
intc_ack_irq (0)
|
||||||
|
timer_interrupt ()
|
||||||
return current
|
return current
|
||||||
|
|
||||||
|
void flush_tlb (unsigned asid):
|
||||||
|
for unsigned tlb = 1; tlb < 32; ++tlb:
|
||||||
|
cp0_set (CP0_INDEX, tlb)
|
||||||
|
__asm__ volatile ("tlbr")
|
||||||
|
unsigned hi
|
||||||
|
cp0_get (CP0_ENTRY_HI, hi)
|
||||||
|
if (hi & 0x1f) == asid:
|
||||||
|
// Set asid to 0, which is only used by the idle task.
|
||||||
|
cp0_set (CP0_ENTRY_HI, 0x2000 * tlb)
|
||||||
|
__asm__ volatile ("tlbwi")
|
||||||
|
|
||||||
|
static void arch_invoke ():
|
||||||
|
Capability *target
|
||||||
|
bool wait
|
||||||
|
Thread *caller = current
|
||||||
|
target = caller->address_space->find_capability (caller->arch.v0, &wait)
|
||||||
|
if !target:
|
||||||
|
// TODO: there must be no action here. This is just because the rest doesn't work yet.
|
||||||
|
dbg_send (3, 2)
|
||||||
|
//dbg_send (caller->arch.v0)
|
||||||
|
schedule ()
|
||||||
|
// Calling an invalid capability always fails.
|
||||||
|
caller->arch.v0 = 0
|
||||||
|
else:
|
||||||
|
if wait:
|
||||||
|
caller->wait ()
|
||||||
|
Capability::Context c
|
||||||
|
c.cap[0] = caller->address_space->find_capability (caller->arch.a0, &c.copy[0])
|
||||||
|
c.cap[1] = caller->address_space->find_capability (caller->arch.a1, &c.copy[1])
|
||||||
|
c.cap[2] = caller->address_space->find_capability (caller->arch.a2, &c.copy[2])
|
||||||
|
c.cap[3] = caller->address_space->find_capability (caller->arch.a3, &c.copy[3])
|
||||||
|
c.data[0] = caller->arch.t0
|
||||||
|
c.data[1] = caller->arch.t1
|
||||||
|
c.data[2] = caller->arch.t2
|
||||||
|
c.data[3] = caller->arch.t3
|
||||||
|
caller->arch.v0 = target->invoke (&c) ? 1 : 0
|
||||||
|
if !current:
|
||||||
|
if caller != &idle && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
|
||||||
|
current = caller
|
||||||
|
else:
|
||||||
|
schedule ()
|
||||||
|
if !current:
|
||||||
|
current = &idle
|
||||||
|
if caller != current:
|
||||||
|
if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
|
||||||
|
if asids[0]:
|
||||||
|
current->address_space->arch.asid = asids[0]
|
||||||
|
asids[0] = asids[asids[0]]
|
||||||
|
else:
|
||||||
|
static unsigned random = 1
|
||||||
|
current->address_space->arch.asid = random
|
||||||
|
// Overwrite used asid, so flush those values from tlb.
|
||||||
|
flush_tlb (random)
|
||||||
|
++random
|
||||||
|
if random >= 64:
|
||||||
|
random = 1
|
||||||
|
asids[current->address_space->arch.asid] = (unsigned)current->address_space
|
||||||
|
cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid)
|
||||||
|
directory = current->address_space->arch.directory
|
||||||
|
unsigned status
|
||||||
|
cp0_get (CP0_STATUS, status)
|
||||||
|
status &= 0x0fffffff
|
||||||
|
if current->flags & THREAD_FLAG_PRIV:
|
||||||
|
status |= 0x10000000
|
||||||
|
cp0_set (CP0_STATUS, status | 0x13)
|
||||||
|
|
||||||
/// A general exception has occurred.
|
/// A general exception has occurred.
|
||||||
Thread *exception ():
|
Thread *exception ():
|
||||||
unsigned cause
|
unsigned cause
|
||||||
|
@ -21,10 +21,12 @@
|
|||||||
#ifndef __JZ4730_HH__
|
#ifndef __JZ4730_HH__
|
||||||
#define __JZ4730_HH__
|
#define __JZ4730_HH__
|
||||||
|
|
||||||
|
// Main clock, for cpu, serial port, and with divisors for most other hardware
|
||||||
#define JZ_EXTAL 3686400
|
#define JZ_EXTAL 3686400
|
||||||
|
// RTC clock
|
||||||
|
#define RTC_CLOCK 32768
|
||||||
|
|
||||||
// Physical addresses are where they really are.
|
// Physical addresses are where they really are.
|
||||||
// (In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2.)
|
|
||||||
#define HARB_PHYSICAL 0x13000000
|
#define HARB_PHYSICAL 0x13000000
|
||||||
#define EMC_PHYSICAL 0x13010000
|
#define EMC_PHYSICAL 0x13010000
|
||||||
#define DMAC_PHYSICAL 0x13020000
|
#define DMAC_PHYSICAL 0x13020000
|
||||||
@ -59,6 +61,7 @@
|
|||||||
#define KBC_PHYSICAL 0x10062000
|
#define KBC_PHYSICAL 0x10062000
|
||||||
|
|
||||||
#ifdef __KERNEL
|
#ifdef __KERNEL
|
||||||
|
// In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2.
|
||||||
#define HARB_BASE (HARB_PHYSICAL + 0xa0000000)
|
#define HARB_BASE (HARB_PHYSICAL + 0xa0000000)
|
||||||
#define EMC_BASE (EMC_PHYSICAL + 0xa0000000)
|
#define EMC_BASE (EMC_PHYSICAL + 0xa0000000)
|
||||||
#define DMAC_BASE (DMAC_PHYSICAL + 0xa0000000)
|
#define DMAC_BASE (DMAC_PHYSICAL + 0xa0000000)
|
||||||
@ -93,8 +96,7 @@
|
|||||||
#define KBC_BASE (KBC_PHYSICAL + 0xa0000000)
|
#define KBC_BASE (KBC_PHYSICAL + 0xa0000000)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include <iris.h>
|
// In user space, they just need a mapping.
|
||||||
// Base addresses are the place where the pages are mapped.
|
|
||||||
#define HARB_BASE 0x00000000
|
#define HARB_BASE 0x00000000
|
||||||
#define EMC_BASE 0x00001000
|
#define EMC_BASE 0x00001000
|
||||||
#define DMAC_BASE 0x00002000
|
#define DMAC_BASE 0x00002000
|
||||||
@ -129,6 +131,7 @@
|
|||||||
#define KBC_BASE 0x0001f000
|
#define KBC_BASE 0x0001f000
|
||||||
|
|
||||||
// Map IO memory (requires a priviledged __my_thread capability).
|
// Map IO memory (requires a priviledged __my_thread capability).
|
||||||
|
#include <iris.h>
|
||||||
static void __map_io (unsigned physical, unsigned mapping):
|
static void __map_io (unsigned physical, unsigned mapping):
|
||||||
Capability page = memory_create_page (__my_memory)
|
Capability page = memory_create_page (__my_memory)
|
||||||
// 0 means not cachable.
|
// 0 means not cachable.
|
||||||
@ -138,7 +141,6 @@ static void __map_io (unsigned physical, unsigned mapping):
|
|||||||
//drop (page)
|
//drop (page)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Physical addresses are where they really are.
|
|
||||||
#define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0)
|
#define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0)
|
||||||
#define map_emc() do { __map_io (EMC_PHYSICAL, EMC_BASE); } while (0)
|
#define map_emc() do { __map_io (EMC_PHYSICAL, EMC_BASE); } while (0)
|
||||||
#define map_dmac() do { __map_io (DMAC_PHYSICAL, DMAC_BASE); } while (0)
|
#define map_dmac() do { __map_io (DMAC_PHYSICAL, DMAC_BASE); } while (0)
|
||||||
@ -2822,6 +2824,25 @@ static __inline__ unsigned msc_calc_slow_clk_divisor (bool is_sd):
|
|||||||
* GPIO
|
* GPIO
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#define GPIO_PW_I_PORT 3
|
||||||
|
#define GPIO_PW_I 1
|
||||||
|
#define GPIO_PW_O_PORT 2
|
||||||
|
#define GPIO_PW_O 2
|
||||||
|
#define GPIO_LED_EN_PORT 2
|
||||||
|
#define GPIO_LED_EN 28
|
||||||
|
#define GPIO_DISP_OFF_N_PORT 2
|
||||||
|
#define GPIO_DISP_OFF_N 29
|
||||||
|
#define GPIO_PWM0_PORT 2
|
||||||
|
#define GPIO_PWM0 30
|
||||||
|
#define GPIO_RTC_IRQ_PORT 3
|
||||||
|
#define GPIO_RTC_IRQ 0
|
||||||
|
#define GPIO_USB_CLK_EN_PORT 0
|
||||||
|
#define GPIO_USB_CLK_EN 29
|
||||||
|
#define GPIO_CHARG_STAT_PORT 3
|
||||||
|
#define GPIO_CHARG_STAT 29
|
||||||
|
#define GPIO_TS_PENIRQ_PORT 2
|
||||||
|
#define GPIO_TS_PENIRQ 4
|
||||||
|
|
||||||
/* Init the alternate function pins */
|
/* Init the alternate function pins */
|
||||||
|
|
||||||
static __inline__ void gpio_as_ssi ():
|
static __inline__ void gpio_as_ssi ():
|
||||||
|
Loading…
Reference in New Issue
Block a user