Merge branch 'for-arm-soc' of git://git.armlinux.org.uk/~rmk/linux-arm into arm/soc
* 'for-arm-soc' of git://git.armlinux.org.uk/~rmk/linux-arm: (21 commits) ARM: sa1100: convert to common clock framework ARM: riscpc: enable chained scatterlist support ARM: riscpc: reduce IRQ handling code ARM: riscpc: move RiscPC assembly files from arch/arm/lib to mach-rpc ARM: riscpc: parse video information from tagged list ARM: riscpc: add ecard quirk for Atomwide 3port serial card ARM: sa1100/neponset: convert serial to use gpiod APIs ARM: sa1100/hackkit: remove empty serial mctrl functions ARM: sa1100/badge4: remove commented out modem control initialisers ARM: sa1100/h3xxx: convert serial to gpiod APIs ARM: sa1100/assabet: convert serial to gpiod APIs serial: sa1100: add note about modem control signals serial: sa1100: add support for mctrl gpios ARM: riscpc: dma: use __iomem pointers for writing DMA ARM: riscpc: dma: improve address/length writing ARM: riscpc: dma: make state a local variable ARM: riscpc: dma: eliminate "cur_sg" scatterlist usage ARM: riscpc: fix DMA ARM: riscpc: fix ecard printing ARM: riscpc: fix lack of keyboard interrupts after irq conversion ... Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
7cba7cacee
|
@ -1231,7 +1231,7 @@ F: include/uapi/drm/panfrost_drm.h
|
||||||
ARM MFM AND FLOPPY DRIVERS
|
ARM MFM AND FLOPPY DRIVERS
|
||||||
M: Ian Molton <spyro@f2s.com>
|
M: Ian Molton <spyro@f2s.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: arch/arm/lib/floppydma.S
|
F: arch/arm/mach-rpc/floppydma.S
|
||||||
F: arch/arm/include/asm/floppy.h
|
F: arch/arm/include/asm/floppy.h
|
||||||
|
|
||||||
ARM PMU PROFILING AND DEBUGGING
|
ARM PMU PROFILING AND DEBUGGING
|
||||||
|
|
|
@ -519,7 +519,7 @@ config ARCH_RPC
|
||||||
select ARCH_ACORN
|
select ARCH_ACORN
|
||||||
select ARCH_MAY_HAVE_PC_FDC
|
select ARCH_MAY_HAVE_PC_FDC
|
||||||
select ARCH_SPARSEMEM_ENABLE
|
select ARCH_SPARSEMEM_ENABLE
|
||||||
select ARCH_USES_GETTIMEOFFSET
|
select ARM_HAS_SG_CHAIN
|
||||||
select CPU_SA110
|
select CPU_SA110
|
||||||
select FIQ
|
select FIQ
|
||||||
select HAVE_IDE
|
select HAVE_IDE
|
||||||
|
@ -540,6 +540,7 @@ config ARCH_SA1100
|
||||||
select CLKSRC_MMIO
|
select CLKSRC_MMIO
|
||||||
select CLKSRC_PXA
|
select CLKSRC_PXA
|
||||||
select TIMER_OF if OF
|
select TIMER_OF if OF
|
||||||
|
select COMMON_CLK
|
||||||
select CPU_FREQ
|
select CPU_FREQ
|
||||||
select CPU_SA1100
|
select CPU_SA1100
|
||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
|
|
|
@ -31,7 +31,6 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ARCH_RPC),y)
|
ifeq ($(CONFIG_ARCH_RPC),y)
|
||||||
lib-y += ecard.o io-acorn.o floppydma.o
|
|
||||||
AFLAGS_delay-loop.o += -march=armv4
|
AFLAGS_delay-loop.o += -march=armv4
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,5 @@
|
||||||
|
|
||||||
# Object file lists.
|
# Object file lists.
|
||||||
|
|
||||||
obj-y := dma.o ecard.o fiq.o irq.o riscpc.o time.o
|
obj-y :=dma.o ecard.o ecard-loader.o fiq.o floppydma.o io-acorn.o irq.o \
|
||||||
|
riscpc.o time.o
|
||||||
|
|
|
@ -27,10 +27,11 @@
|
||||||
|
|
||||||
struct iomd_dma {
|
struct iomd_dma {
|
||||||
struct dma_struct dma;
|
struct dma_struct dma;
|
||||||
unsigned int state;
|
void __iomem *base; /* Controller base address */
|
||||||
unsigned long base; /* Controller base address */
|
|
||||||
int irq; /* Controller IRQ */
|
int irq; /* Controller IRQ */
|
||||||
struct scatterlist cur_sg; /* Current controller buffer */
|
unsigned int state;
|
||||||
|
dma_addr_t cur_addr;
|
||||||
|
unsigned int cur_len;
|
||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
unsigned int dma_len;
|
unsigned int dma_len;
|
||||||
};
|
};
|
||||||
|
@ -53,13 +54,13 @@ typedef enum {
|
||||||
#define CR (IOMD_IO0CR - IOMD_IO0CURA)
|
#define CR (IOMD_IO0CR - IOMD_IO0CURA)
|
||||||
#define ST (IOMD_IO0ST - IOMD_IO0CURA)
|
#define ST (IOMD_IO0ST - IOMD_IO0CURA)
|
||||||
|
|
||||||
static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
|
static void iomd_get_next_sg(struct iomd_dma *idma)
|
||||||
{
|
{
|
||||||
unsigned long end, offset, flags = 0;
|
unsigned long end, offset, flags = 0;
|
||||||
|
|
||||||
if (idma->dma.sg) {
|
if (idma->dma.sg) {
|
||||||
sg->dma_address = idma->dma_addr;
|
idma->cur_addr = idma->dma_addr;
|
||||||
offset = sg->dma_address & ~PAGE_MASK;
|
offset = idma->cur_addr & ~PAGE_MASK;
|
||||||
|
|
||||||
end = offset + idma->dma_len;
|
end = offset + idma->dma_len;
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
|
||||||
if (offset + TRANSFER_SIZE >= end)
|
if (offset + TRANSFER_SIZE >= end)
|
||||||
flags |= DMA_END_L;
|
flags |= DMA_END_L;
|
||||||
|
|
||||||
sg->length = end - TRANSFER_SIZE;
|
idma->cur_len = end - TRANSFER_SIZE;
|
||||||
|
|
||||||
idma->dma_len -= end - offset;
|
idma->dma_len -= end - offset;
|
||||||
idma->dma_addr += end - offset;
|
idma->dma_addr += end - offset;
|
||||||
|
@ -87,52 +88,49 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
flags = DMA_END_S | DMA_END_L;
|
flags = DMA_END_S | DMA_END_L;
|
||||||
sg->dma_address = 0;
|
idma->cur_addr = 0;
|
||||||
sg->length = 0;
|
idma->cur_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sg->length |= flags;
|
idma->cur_len |= flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
|
static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct iomd_dma *idma = dev_id;
|
struct iomd_dma *idma = dev_id;
|
||||||
unsigned long base = idma->base;
|
void __iomem *base = idma->base;
|
||||||
|
unsigned int state = idma->state;
|
||||||
|
unsigned int status, cur, end;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
unsigned int status;
|
status = readb(base + ST);
|
||||||
|
|
||||||
status = iomd_readb(base + ST);
|
|
||||||
if (!(status & DMA_ST_INT))
|
if (!(status & DMA_ST_INT))
|
||||||
return IRQ_HANDLED;
|
goto out;
|
||||||
|
|
||||||
if ((idma->state ^ status) & DMA_ST_AB)
|
if ((state ^ status) & DMA_ST_AB)
|
||||||
iomd_get_next_sg(&idma->cur_sg, idma);
|
iomd_get_next_sg(idma);
|
||||||
|
|
||||||
switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
|
// This efficiently implements state = OFL != AB ? AB : 0
|
||||||
case DMA_ST_OFL: /* OIA */
|
state = ((status >> 2) ^ status) & DMA_ST_AB;
|
||||||
case DMA_ST_AB: /* .IB */
|
if (state) {
|
||||||
iomd_writel(idma->cur_sg.dma_address, base + CURA);
|
cur = CURA;
|
||||||
iomd_writel(idma->cur_sg.length, base + ENDA);
|
end = ENDA;
|
||||||
idma->state = DMA_ST_AB;
|
} else {
|
||||||
break;
|
cur = CURB;
|
||||||
|
end = ENDB;
|
||||||
case DMA_ST_OFL | DMA_ST_AB: /* OIB */
|
|
||||||
case 0: /* .IA */
|
|
||||||
iomd_writel(idma->cur_sg.dma_address, base + CURB);
|
|
||||||
iomd_writel(idma->cur_sg.length, base + ENDB);
|
|
||||||
idma->state = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
writel(idma->cur_addr, base + cur);
|
||||||
|
writel(idma->cur_len, base + end);
|
||||||
|
|
||||||
if (status & DMA_ST_OFL &&
|
if (status & DMA_ST_OFL &&
|
||||||
idma->cur_sg.length == (DMA_END_S|DMA_END_L))
|
idma->cur_len == (DMA_END_S|DMA_END_L))
|
||||||
break;
|
break;
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
idma->state = ~DMA_ST_AB;
|
state = ~DMA_ST_AB;
|
||||||
disable_irq(irq);
|
disable_irq_nosync(irq);
|
||||||
|
out:
|
||||||
|
idma->state = state;
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +158,7 @@ static struct device isa_dma_dev = {
|
||||||
static void iomd_enable_dma(unsigned int chan, dma_t *dma)
|
static void iomd_enable_dma(unsigned int chan, dma_t *dma)
|
||||||
{
|
{
|
||||||
struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
|
struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
|
||||||
unsigned long dma_base = idma->base;
|
void __iomem *base = idma->base;
|
||||||
unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
|
unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
|
||||||
|
|
||||||
if (idma->dma.invalid) {
|
if (idma->dma.invalid) {
|
||||||
|
@ -180,27 +178,30 @@ static void iomd_enable_dma(unsigned int chan, dma_t *dma)
|
||||||
DMA_FROM_DEVICE : DMA_TO_DEVICE);
|
DMA_FROM_DEVICE : DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
iomd_writeb(DMA_CR_C, dma_base + CR);
|
idma->dma_addr = idma->dma.sg->dma_address;
|
||||||
|
idma->dma_len = idma->dma.sg->length;
|
||||||
|
|
||||||
|
writeb(DMA_CR_C, base + CR);
|
||||||
idma->state = DMA_ST_AB;
|
idma->state = DMA_ST_AB;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idma->dma.dma_mode == DMA_MODE_READ)
|
if (idma->dma.dma_mode == DMA_MODE_READ)
|
||||||
ctrl |= DMA_CR_D;
|
ctrl |= DMA_CR_D;
|
||||||
|
|
||||||
iomd_writeb(ctrl, dma_base + CR);
|
writeb(ctrl, base + CR);
|
||||||
enable_irq(idma->irq);
|
enable_irq(idma->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iomd_disable_dma(unsigned int chan, dma_t *dma)
|
static void iomd_disable_dma(unsigned int chan, dma_t *dma)
|
||||||
{
|
{
|
||||||
struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
|
struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
|
||||||
unsigned long dma_base = idma->base;
|
void __iomem *base = idma->base;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
if (idma->state != ~DMA_ST_AB)
|
if (idma->state != ~DMA_ST_AB)
|
||||||
disable_irq(idma->irq);
|
disable_irq(idma->irq);
|
||||||
iomd_writeb(0, dma_base + CR);
|
writeb(0, base + CR);
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,17 +364,17 @@ static int __init rpc_dma_init(void)
|
||||||
*/
|
*/
|
||||||
iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
|
iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
|
||||||
|
|
||||||
iomd_dma[DMA_0].base = IOMD_IO0CURA;
|
iomd_dma[DMA_0].base = IOMD_BASE + IOMD_IO0CURA;
|
||||||
iomd_dma[DMA_0].irq = IRQ_DMA0;
|
iomd_dma[DMA_0].irq = IRQ_DMA0;
|
||||||
iomd_dma[DMA_1].base = IOMD_IO1CURA;
|
iomd_dma[DMA_1].base = IOMD_BASE + IOMD_IO1CURA;
|
||||||
iomd_dma[DMA_1].irq = IRQ_DMA1;
|
iomd_dma[DMA_1].irq = IRQ_DMA1;
|
||||||
iomd_dma[DMA_2].base = IOMD_IO2CURA;
|
iomd_dma[DMA_2].base = IOMD_BASE + IOMD_IO2CURA;
|
||||||
iomd_dma[DMA_2].irq = IRQ_DMA2;
|
iomd_dma[DMA_2].irq = IRQ_DMA2;
|
||||||
iomd_dma[DMA_3].base = IOMD_IO3CURA;
|
iomd_dma[DMA_3].base = IOMD_BASE + IOMD_IO3CURA;
|
||||||
iomd_dma[DMA_3].irq = IRQ_DMA3;
|
iomd_dma[DMA_3].irq = IRQ_DMA3;
|
||||||
iomd_dma[DMA_S0].base = IOMD_SD0CURA;
|
iomd_dma[DMA_S0].base = IOMD_BASE + IOMD_SD0CURA;
|
||||||
iomd_dma[DMA_S0].irq = IRQ_DMAS0;
|
iomd_dma[DMA_S0].irq = IRQ_DMAS0;
|
||||||
iomd_dma[DMA_S1].base = IOMD_SD1CURA;
|
iomd_dma[DMA_S1].base = IOMD_BASE + IOMD_SD1CURA;
|
||||||
iomd_dma[DMA_S1].irq = IRQ_DMAS1;
|
iomd_dma[DMA_S1].irq = IRQ_DMAS1;
|
||||||
|
|
||||||
for (i = DMA_0; i <= DMA_S1; i++) {
|
for (i = DMA_0; i <= DMA_S1; i++) {
|
||||||
|
|
|
@ -70,17 +70,21 @@ struct expcard_blacklist {
|
||||||
unsigned short manufacturer;
|
unsigned short manufacturer;
|
||||||
unsigned short product;
|
unsigned short product;
|
||||||
const char *type;
|
const char *type;
|
||||||
|
void (*init)(ecard_t *ec);
|
||||||
};
|
};
|
||||||
|
|
||||||
static ecard_t *cards;
|
static ecard_t *cards;
|
||||||
static ecard_t *slot_to_expcard[MAX_ECARDS];
|
static ecard_t *slot_to_expcard[MAX_ECARDS];
|
||||||
static unsigned int ectcr;
|
static unsigned int ectcr;
|
||||||
|
|
||||||
|
static void atomwide_3p_quirk(ecard_t *ec);
|
||||||
|
|
||||||
/* List of descriptions of cards which don't have an extended
|
/* List of descriptions of cards which don't have an extended
|
||||||
* identification, or chunk directories containing a description.
|
* identification, or chunk directories containing a description.
|
||||||
*/
|
*/
|
||||||
static struct expcard_blacklist __initdata blacklist[] = {
|
static struct expcard_blacklist __initdata blacklist[] = {
|
||||||
{ MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" }
|
{ MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" },
|
||||||
|
{ MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, NULL, atomwide_3p_quirk },
|
||||||
};
|
};
|
||||||
|
|
||||||
asmlinkage extern int
|
asmlinkage extern int
|
||||||
|
@ -496,18 +500,21 @@ static void ecard_dump_irq_state(void)
|
||||||
printk("Expansion card IRQ state:\n");
|
printk("Expansion card IRQ state:\n");
|
||||||
|
|
||||||
for (ec = cards; ec; ec = ec->next) {
|
for (ec = cards; ec; ec = ec->next) {
|
||||||
|
const char *claimed;
|
||||||
|
|
||||||
if (ec->slot_no == 8)
|
if (ec->slot_no == 8)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
printk(" %d: %sclaimed, ",
|
claimed = ec->claimed ? "" : "not ";
|
||||||
ec->slot_no, ec->claimed ? "" : "not ");
|
|
||||||
|
|
||||||
if (ec->ops && ec->ops->irqpending &&
|
if (ec->ops && ec->ops->irqpending &&
|
||||||
ec->ops != &ecard_default_ops)
|
ec->ops != &ecard_default_ops)
|
||||||
printk("irq %spending\n",
|
printk(" %d: %sclaimed irq %spending\n",
|
||||||
|
ec->slot_no, claimed,
|
||||||
ec->ops->irqpending(ec) ? "" : "not ");
|
ec->ops->irqpending(ec) ? "" : "not ");
|
||||||
else
|
else
|
||||||
printk("irqaddr %p, mask = %02X, status = %02X\n",
|
printk(" %d: %sclaimed irqaddr %p, mask = %02X, status = %02X\n",
|
||||||
|
ec->slot_no, claimed,
|
||||||
ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
|
ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -868,6 +875,16 @@ void __iomem *ecardm_iomap(struct expansion_card *ec, unsigned int res,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ecardm_iomap);
|
EXPORT_SYMBOL(ecardm_iomap);
|
||||||
|
|
||||||
|
static void atomwide_3p_quirk(ecard_t *ec)
|
||||||
|
{
|
||||||
|
void __iomem *addr = __ecard_address(ec, ECARD_IOC, ECARD_SYNC);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Disable interrupts on each port */
|
||||||
|
for (i = 0x2000; i <= 0x2800; i += 0x0400)
|
||||||
|
writeb(0, addr + i + 4);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Probe for an expansion card.
|
* Probe for an expansion card.
|
||||||
*
|
*
|
||||||
|
@ -924,7 +941,10 @@ static int __init ecard_probe(int slot, unsigned irq, card_type_t type)
|
||||||
for (i = 0; i < ARRAY_SIZE(blacklist); i++)
|
for (i = 0; i < ARRAY_SIZE(blacklist); i++)
|
||||||
if (blacklist[i].manufacturer == ec->cid.manufacturer &&
|
if (blacklist[i].manufacturer == ec->cid.manufacturer &&
|
||||||
blacklist[i].product == ec->cid.product) {
|
blacklist[i].product == ec->cid.product) {
|
||||||
|
if (blacklist[i].type)
|
||||||
ec->card_desc = blacklist[i].type;
|
ec->card_desc = blacklist[i].type;
|
||||||
|
if (blacklist[i].init)
|
||||||
|
blacklist[i].init(ec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,29 +118,22 @@ static void arch_decomp_setup(void)
|
||||||
struct tag *t = (struct tag *)params;
|
struct tag *t = (struct tag *)params;
|
||||||
unsigned int nr_pages = 0, page_size = PAGE_SIZE;
|
unsigned int nr_pages = 0, page_size = PAGE_SIZE;
|
||||||
|
|
||||||
if (t->hdr.tag == ATAG_CORE)
|
if (t->hdr.tag == ATAG_CORE) {
|
||||||
{
|
for (; t->hdr.size; t = tag_next(t)) {
|
||||||
for (; t->hdr.size; t = tag_next(t))
|
if (t->hdr.tag == ATAG_VIDEOTEXT) {
|
||||||
{
|
|
||||||
if (t->hdr.tag == ATAG_VIDEOTEXT)
|
|
||||||
{
|
|
||||||
video_num_rows = t->u.videotext.video_lines;
|
video_num_rows = t->u.videotext.video_lines;
|
||||||
video_num_cols = t->u.videotext.video_cols;
|
video_num_cols = t->u.videotext.video_cols;
|
||||||
bytes_per_char_h = t->u.videotext.video_points;
|
|
||||||
bytes_per_char_v = t->u.videotext.video_points;
|
|
||||||
video_x = t->u.videotext.x;
|
video_x = t->u.videotext.x;
|
||||||
video_y = t->u.videotext.y;
|
video_y = t->u.videotext.y;
|
||||||
}
|
} else if (t->hdr.tag == ATAG_VIDEOLFB) {
|
||||||
|
bytes_per_char_h = t->u.videolfb.lfb_depth;
|
||||||
if (t->hdr.tag == ATAG_MEM)
|
bytes_per_char_v = 8;
|
||||||
{
|
} else if (t->hdr.tag == ATAG_MEM) {
|
||||||
page_size = PAGE_SIZE;
|
page_size = PAGE_SIZE;
|
||||||
nr_pages += (t->u.mem.size / PAGE_SIZE);
|
nr_pages += (t->u.mem.size / PAGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nr_pages = params->nr_pages;
|
nr_pages = params->nr_pages;
|
||||||
page_size = params->page_size;
|
page_size = params->page_size;
|
||||||
video_num_rows = params->video_num_rows;
|
video_num_rows = params->video_num_rows;
|
||||||
|
|
|
@ -8,117 +8,71 @@
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/fiq.h>
|
#include <asm/fiq.h>
|
||||||
|
|
||||||
static void iomd_ack_irq_a(struct irq_data *d)
|
// These are offsets from the stat register for each IRQ bank
|
||||||
{
|
#define STAT 0x00
|
||||||
unsigned int val, mask;
|
#define REQ 0x04
|
||||||
|
#define CLR 0x04
|
||||||
|
#define MASK 0x08
|
||||||
|
|
||||||
mask = 1 << d->irq;
|
static void __iomem *iomd_get_base(struct irq_data *d)
|
||||||
val = iomd_readb(IOMD_IRQMASKA);
|
{
|
||||||
iomd_writeb(val & ~mask, IOMD_IRQMASKA);
|
void *cd = irq_data_get_irq_chip_data(d);
|
||||||
iomd_writeb(mask, IOMD_IRQCLRA);
|
|
||||||
|
return (void __iomem *)(unsigned long)cd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iomd_mask_irq_a(struct irq_data *d)
|
static void iomd_set_base_mask(unsigned int irq, void __iomem *base, u32 mask)
|
||||||
{
|
{
|
||||||
unsigned int val, mask;
|
struct irq_data *d = irq_get_irq_data(irq);
|
||||||
|
|
||||||
mask = 1 << d->irq;
|
d->mask = mask;
|
||||||
val = iomd_readb(IOMD_IRQMASKA);
|
irq_set_chip_data(irq, (void *)(unsigned long)base);
|
||||||
iomd_writeb(val & ~mask, IOMD_IRQMASKA);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iomd_unmask_irq_a(struct irq_data *d)
|
static void iomd_irq_mask_ack(struct irq_data *d)
|
||||||
{
|
{
|
||||||
unsigned int val, mask;
|
void __iomem *base = iomd_get_base(d);
|
||||||
|
unsigned int val, mask = d->mask;
|
||||||
|
|
||||||
mask = 1 << d->irq;
|
val = readb(base + MASK);
|
||||||
val = iomd_readb(IOMD_IRQMASKA);
|
writeb(val & ~mask, base + MASK);
|
||||||
iomd_writeb(val | mask, IOMD_IRQMASKA);
|
writeb(mask, base + CLR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_chip iomd_a_chip = {
|
static void iomd_irq_mask(struct irq_data *d)
|
||||||
.irq_ack = iomd_ack_irq_a,
|
{
|
||||||
.irq_mask = iomd_mask_irq_a,
|
void __iomem *base = iomd_get_base(d);
|
||||||
.irq_unmask = iomd_unmask_irq_a,
|
unsigned int val, mask = d->mask;
|
||||||
|
|
||||||
|
val = readb(base + MASK);
|
||||||
|
writeb(val & ~mask, base + MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iomd_irq_unmask(struct irq_data *d)
|
||||||
|
{
|
||||||
|
void __iomem *base = iomd_get_base(d);
|
||||||
|
unsigned int val, mask = d->mask;
|
||||||
|
|
||||||
|
val = readb(base + MASK);
|
||||||
|
writeb(val | mask, base + MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct irq_chip iomd_chip_clr = {
|
||||||
|
.irq_mask_ack = iomd_irq_mask_ack,
|
||||||
|
.irq_mask = iomd_irq_mask,
|
||||||
|
.irq_unmask = iomd_irq_unmask,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void iomd_mask_irq_b(struct irq_data *d)
|
static struct irq_chip iomd_chip_noclr = {
|
||||||
{
|
.irq_mask = iomd_irq_mask,
|
||||||
unsigned int val, mask;
|
.irq_unmask = iomd_irq_unmask,
|
||||||
|
|
||||||
mask = 1 << (d->irq & 7);
|
|
||||||
val = iomd_readb(IOMD_IRQMASKB);
|
|
||||||
iomd_writeb(val & ~mask, IOMD_IRQMASKB);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iomd_unmask_irq_b(struct irq_data *d)
|
|
||||||
{
|
|
||||||
unsigned int val, mask;
|
|
||||||
|
|
||||||
mask = 1 << (d->irq & 7);
|
|
||||||
val = iomd_readb(IOMD_IRQMASKB);
|
|
||||||
iomd_writeb(val | mask, IOMD_IRQMASKB);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct irq_chip iomd_b_chip = {
|
|
||||||
.irq_ack = iomd_mask_irq_b,
|
|
||||||
.irq_mask = iomd_mask_irq_b,
|
|
||||||
.irq_unmask = iomd_unmask_irq_b,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void iomd_mask_irq_dma(struct irq_data *d)
|
|
||||||
{
|
|
||||||
unsigned int val, mask;
|
|
||||||
|
|
||||||
mask = 1 << (d->irq & 7);
|
|
||||||
val = iomd_readb(IOMD_DMAMASK);
|
|
||||||
iomd_writeb(val & ~mask, IOMD_DMAMASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iomd_unmask_irq_dma(struct irq_data *d)
|
|
||||||
{
|
|
||||||
unsigned int val, mask;
|
|
||||||
|
|
||||||
mask = 1 << (d->irq & 7);
|
|
||||||
val = iomd_readb(IOMD_DMAMASK);
|
|
||||||
iomd_writeb(val | mask, IOMD_DMAMASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct irq_chip iomd_dma_chip = {
|
|
||||||
.irq_ack = iomd_mask_irq_dma,
|
|
||||||
.irq_mask = iomd_mask_irq_dma,
|
|
||||||
.irq_unmask = iomd_unmask_irq_dma,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void iomd_mask_irq_fiq(struct irq_data *d)
|
|
||||||
{
|
|
||||||
unsigned int val, mask;
|
|
||||||
|
|
||||||
mask = 1 << (d->irq & 7);
|
|
||||||
val = iomd_readb(IOMD_FIQMASK);
|
|
||||||
iomd_writeb(val & ~mask, IOMD_FIQMASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iomd_unmask_irq_fiq(struct irq_data *d)
|
|
||||||
{
|
|
||||||
unsigned int val, mask;
|
|
||||||
|
|
||||||
mask = 1 << (d->irq & 7);
|
|
||||||
val = iomd_readb(IOMD_FIQMASK);
|
|
||||||
iomd_writeb(val | mask, IOMD_FIQMASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct irq_chip iomd_fiq_chip = {
|
|
||||||
.irq_ack = iomd_mask_irq_fiq,
|
|
||||||
.irq_mask = iomd_mask_irq_fiq,
|
|
||||||
.irq_unmask = iomd_unmask_irq_fiq,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
|
extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
|
||||||
|
|
||||||
void __init rpc_init_irq(void)
|
void __init rpc_init_irq(void)
|
||||||
{
|
{
|
||||||
unsigned int irq, clr, set = 0;
|
unsigned int irq, clr, set;
|
||||||
|
|
||||||
iomd_writeb(0, IOMD_IRQMASKA);
|
iomd_writeb(0, IOMD_IRQMASKA);
|
||||||
iomd_writeb(0, IOMD_IRQMASKB);
|
iomd_writeb(0, IOMD_IRQMASKB);
|
||||||
|
@ -130,6 +84,7 @@ void __init rpc_init_irq(void)
|
||||||
|
|
||||||
for (irq = 0; irq < NR_IRQS; irq++) {
|
for (irq = 0; irq < NR_IRQS; irq++) {
|
||||||
clr = IRQ_NOREQUEST;
|
clr = IRQ_NOREQUEST;
|
||||||
|
set = 0;
|
||||||
|
|
||||||
if (irq <= 6 || (irq >= 9 && irq <= 15))
|
if (irq <= 6 || (irq >= 9 && irq <= 15))
|
||||||
clr |= IRQ_NOPROBE;
|
clr |= IRQ_NOPROBE;
|
||||||
|
@ -140,30 +95,37 @@ void __init rpc_init_irq(void)
|
||||||
|
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
case 0 ... 7:
|
case 0 ... 7:
|
||||||
irq_set_chip_and_handler(irq, &iomd_a_chip,
|
irq_set_chip_and_handler(irq, &iomd_chip_clr,
|
||||||
handle_level_irq);
|
handle_level_irq);
|
||||||
irq_modify_status(irq, clr, set);
|
irq_modify_status(irq, clr, set);
|
||||||
|
iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATA,
|
||||||
|
BIT(irq));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8 ... 15:
|
case 8 ... 15:
|
||||||
irq_set_chip_and_handler(irq, &iomd_b_chip,
|
irq_set_chip_and_handler(irq, &iomd_chip_noclr,
|
||||||
handle_level_irq);
|
handle_level_irq);
|
||||||
irq_modify_status(irq, clr, set);
|
irq_modify_status(irq, clr, set);
|
||||||
|
iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATB,
|
||||||
|
BIT(irq - 8));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16 ... 21:
|
case 16 ... 21:
|
||||||
irq_set_chip_and_handler(irq, &iomd_dma_chip,
|
irq_set_chip_and_handler(irq, &iomd_chip_noclr,
|
||||||
handle_level_irq);
|
handle_level_irq);
|
||||||
irq_modify_status(irq, clr, set);
|
irq_modify_status(irq, clr, set);
|
||||||
|
iomd_set_base_mask(irq, IOMD_BASE + IOMD_DMASTAT,
|
||||||
|
BIT(irq - 16));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 64 ... 71:
|
case 64 ... 71:
|
||||||
irq_set_chip(irq, &iomd_fiq_chip);
|
irq_set_chip(irq, &iomd_chip_noclr);
|
||||||
irq_modify_status(irq, clr, set);
|
irq_modify_status(irq, clr, set);
|
||||||
|
iomd_set_base_mask(irq, IOMD_BASE + IOMD_FIQSTAT,
|
||||||
|
BIT(irq - 64));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init_FIQ(FIQ_START);
|
init_FIQ(FIQ_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* 04-Dec-1997 RMK Updated for new arch/arm/time.c
|
* 04-Dec-1997 RMK Updated for new arch/arm/time.c
|
||||||
* 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500
|
* 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500
|
||||||
*/
|
*/
|
||||||
#include <linux/timex.h>
|
#include <linux/clocksource.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
|
@ -27,11 +27,15 @@
|
||||||
#define RPC_CLOCK_FREQ 2000000
|
#define RPC_CLOCK_FREQ 2000000
|
||||||
#define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
|
#define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
|
||||||
|
|
||||||
static u32 ioc_timer_gettimeoffset(void)
|
static u32 ioc_time;
|
||||||
|
|
||||||
|
static u64 ioc_timer_read(struct clocksource *cs)
|
||||||
{
|
{
|
||||||
unsigned int count1, count2, status;
|
unsigned int count1, count2, status;
|
||||||
long offset;
|
unsigned long flags;
|
||||||
|
u32 ticks;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
ioc_writeb (0, IOC_T0LATCH);
|
ioc_writeb (0, IOC_T0LATCH);
|
||||||
barrier ();
|
barrier ();
|
||||||
count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
|
count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
|
||||||
|
@ -41,27 +45,34 @@ static u32 ioc_timer_gettimeoffset(void)
|
||||||
ioc_writeb (0, IOC_T0LATCH);
|
ioc_writeb (0, IOC_T0LATCH);
|
||||||
barrier ();
|
barrier ();
|
||||||
count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
|
count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
|
||||||
|
ticks = ioc_time + RPC_LATCH - count2;
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
offset = count2;
|
|
||||||
if (count2 < count1) {
|
if (count2 < count1) {
|
||||||
/*
|
/*
|
||||||
* We have not had an interrupt between reading count1
|
* The timer has not reloaded between reading count1 and
|
||||||
* and count2.
|
* count2, check whether an interrupt was actually pending.
|
||||||
*/
|
*/
|
||||||
if (status & (1 << 5))
|
if (status & (1 << 5))
|
||||||
offset -= RPC_LATCH;
|
ticks += RPC_LATCH;
|
||||||
} else if (count2 > count1) {
|
} else if (count2 > count1) {
|
||||||
/*
|
/*
|
||||||
* We have just had another interrupt between reading
|
* The timer has reloaded, so count2 indicates the new
|
||||||
* count1 and count2.
|
* count since the wrap. The interrupt would not have
|
||||||
|
* been processed, so add the missed ticks.
|
||||||
*/
|
*/
|
||||||
offset -= RPC_LATCH;
|
ticks += RPC_LATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = (RPC_LATCH - offset) * (tick_nsec / 1000);
|
return ticks;
|
||||||
return DIV_ROUND_CLOSEST(offset, RPC_LATCH) * 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct clocksource ioctime_clocksource = {
|
||||||
|
.read = ioc_timer_read,
|
||||||
|
.mask = CLOCKSOURCE_MASK(32),
|
||||||
|
.rating = 100,
|
||||||
|
};
|
||||||
|
|
||||||
void __init ioctime_init(void)
|
void __init ioctime_init(void)
|
||||||
{
|
{
|
||||||
ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
|
ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
|
||||||
|
@ -72,6 +83,7 @@ void __init ioctime_init(void)
|
||||||
static irqreturn_t
|
static irqreturn_t
|
||||||
ioc_timer_interrupt(int irq, void *dev_id)
|
ioc_timer_interrupt(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
|
ioc_time += RPC_LATCH;
|
||||||
timer_tick();
|
timer_tick();
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +98,7 @@ static struct irqaction ioc_timer_irq = {
|
||||||
*/
|
*/
|
||||||
void __init ioc_timer_init(void)
|
void __init ioc_timer_init(void)
|
||||||
{
|
{
|
||||||
arch_gettimeoffset = ioc_timer_gettimeoffset;
|
WARN_ON(clocksource_register_hz(&ioctime_clocksource, RPC_CLOCK_FREQ));
|
||||||
ioctime_init();
|
ioctime_init();
|
||||||
setup_irq(IRQ_TIMER0, &ioc_timer_irq);
|
setup_irq(IRQ_TIMER0, &ioc_timer_irq);
|
||||||
}
|
}
|
||||||
|
|
|
@ -522,6 +522,29 @@ static const struct gpio_keys_platform_data assabet_keys_pdata = {
|
||||||
.rep = 0,
|
.rep = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table assabet_uart1_gpio_table = {
|
||||||
|
.dev_id = "sa11x0-uart.1",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP("assabet", 16, "dtr", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("assabet", 17, "rts", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("assabet", 25, "dcd", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("assabet", 26, "cts", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("assabet", 27, "dsr", GPIO_ACTIVE_LOW),
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table assabet_uart3_gpio_table = {
|
||||||
|
.dev_id = "sa11x0-uart.3",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP("assabet", 28, "cts", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("assabet", 29, "dsr", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("assabet", 30, "dcd", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("assabet", 31, "rng", GPIO_ACTIVE_LOW),
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static void __init assabet_init(void)
|
static void __init assabet_init(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -568,7 +591,10 @@ static void __init assabet_init(void)
|
||||||
neponset_resources, ARRAY_SIZE(neponset_resources));
|
neponset_resources, ARRAY_SIZE(neponset_resources));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
gpiod_add_lookup_table(&assabet_uart1_gpio_table);
|
||||||
|
gpiod_add_lookup_table(&assabet_uart3_gpio_table);
|
||||||
gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);
|
gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);
|
||||||
|
|
||||||
sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata,
|
sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata,
|
||||||
assabet_cf_vcc_consumers,
|
assabet_cf_vcc_consumers,
|
||||||
ARRAY_SIZE(assabet_cf_vcc_consumers),
|
ARRAY_SIZE(assabet_cf_vcc_consumers),
|
||||||
|
@ -658,74 +684,13 @@ static void assabet_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
|
||||||
{
|
{
|
||||||
if (port->mapbase == _Ser1UTCR0) {
|
if (port->mapbase == _Ser1UTCR0) {
|
||||||
if (state)
|
if (state)
|
||||||
ASSABET_BCR_clear(ASSABET_BCR_RS232EN |
|
ASSABET_BCR_clear(ASSABET_BCR_RS232EN);
|
||||||
ASSABET_BCR_COM_RTS |
|
|
||||||
ASSABET_BCR_COM_DTR);
|
|
||||||
else
|
else
|
||||||
ASSABET_BCR_set(ASSABET_BCR_RS232EN |
|
ASSABET_BCR_set(ASSABET_BCR_RS232EN);
|
||||||
ASSABET_BCR_COM_RTS |
|
|
||||||
ASSABET_BCR_COM_DTR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Assabet uses COM_RTS and COM_DTR for both UART1 (com port)
|
|
||||||
* and UART3 (radio module). We only handle them for UART1 here.
|
|
||||||
*/
|
|
||||||
static void assabet_set_mctrl(struct uart_port *port, u_int mctrl)
|
|
||||||
{
|
|
||||||
if (port->mapbase == _Ser1UTCR0) {
|
|
||||||
u_int set = 0, clear = 0;
|
|
||||||
|
|
||||||
if (mctrl & TIOCM_RTS)
|
|
||||||
clear |= ASSABET_BCR_COM_RTS;
|
|
||||||
else
|
|
||||||
set |= ASSABET_BCR_COM_RTS;
|
|
||||||
|
|
||||||
if (mctrl & TIOCM_DTR)
|
|
||||||
clear |= ASSABET_BCR_COM_DTR;
|
|
||||||
else
|
|
||||||
set |= ASSABET_BCR_COM_DTR;
|
|
||||||
|
|
||||||
ASSABET_BCR_clear(clear);
|
|
||||||
ASSABET_BCR_set(set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static u_int assabet_get_mctrl(struct uart_port *port)
|
|
||||||
{
|
|
||||||
u_int ret = 0;
|
|
||||||
u_int bsr = ASSABET_BSR;
|
|
||||||
|
|
||||||
/* need 2 reads to read current value */
|
|
||||||
bsr = ASSABET_BSR;
|
|
||||||
|
|
||||||
if (port->mapbase == _Ser1UTCR0) {
|
|
||||||
if (bsr & ASSABET_BSR_COM_DCD)
|
|
||||||
ret |= TIOCM_CD;
|
|
||||||
if (bsr & ASSABET_BSR_COM_CTS)
|
|
||||||
ret |= TIOCM_CTS;
|
|
||||||
if (bsr & ASSABET_BSR_COM_DSR)
|
|
||||||
ret |= TIOCM_DSR;
|
|
||||||
} else if (port->mapbase == _Ser3UTCR0) {
|
|
||||||
if (bsr & ASSABET_BSR_RAD_DCD)
|
|
||||||
ret |= TIOCM_CD;
|
|
||||||
if (bsr & ASSABET_BSR_RAD_CTS)
|
|
||||||
ret |= TIOCM_CTS;
|
|
||||||
if (bsr & ASSABET_BSR_RAD_DSR)
|
|
||||||
ret |= TIOCM_DSR;
|
|
||||||
if (bsr & ASSABET_BSR_RAD_RI)
|
|
||||||
ret |= TIOCM_RI;
|
|
||||||
} else {
|
|
||||||
ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct sa1100_port_fns assabet_port_fns __initdata = {
|
static struct sa1100_port_fns assabet_port_fns __initdata = {
|
||||||
.set_mctrl = assabet_set_mctrl,
|
|
||||||
.get_mctrl = assabet_get_mctrl,
|
|
||||||
.pm = assabet_uart_pm,
|
.pm = assabet_uart_pm,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -315,8 +315,6 @@ badge4_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sa1100_port_fns badge4_port_fns __initdata = {
|
static struct sa1100_port_fns badge4_port_fns __initdata = {
|
||||||
//.get_mctrl = badge4_get_mctrl,
|
|
||||||
//.set_mctrl = badge4_set_mctrl,
|
|
||||||
.pm = badge4_uart_pm,
|
.pm = badge4_uart_pm,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,176 +2,144 @@
|
||||||
/*
|
/*
|
||||||
* linux/arch/arm/mach-sa1100/clock.c
|
* linux/arch/arm/mach-sa1100/clock.c
|
||||||
*/
|
*/
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/string.h>
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/clkdev.h>
|
#include <linux/clkdev.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <mach/generic.h>
|
#include <mach/generic.h>
|
||||||
|
|
||||||
struct clkops {
|
static const char * const clk_tucr_parents[] = {
|
||||||
void (*enable)(struct clk *);
|
"clk32768", "clk3686400",
|
||||||
void (*disable)(struct clk *);
|
|
||||||
unsigned long (*get_rate)(struct clk *);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct clk {
|
static DEFINE_SPINLOCK(tucr_lock);
|
||||||
const struct clkops *ops;
|
|
||||||
unsigned int enabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEFINE_CLK(_name, _ops) \
|
static int clk_gpio27_enable(struct clk_hw *hw)
|
||||||
struct clk clk_##_name = { \
|
|
||||||
.ops = _ops, \
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(clocks_lock);
|
|
||||||
|
|
||||||
/* Dummy clk routine to build generic kernel parts that may be using them */
|
|
||||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
|
||||||
{
|
{
|
||||||
return clk_get_rate(clk);
|
unsigned long flags;
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(clk_round_rate);
|
|
||||||
|
|
||||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(clk_set_rate);
|
|
||||||
|
|
||||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(clk_set_parent);
|
|
||||||
|
|
||||||
struct clk *clk_get_parent(struct clk *clk)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(clk_get_parent);
|
|
||||||
|
|
||||||
static void clk_gpio27_enable(struct clk *clk)
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
|
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
|
||||||
* (SA-1110 Developer's Manual, section 9.1.2.1)
|
* (SA-1110 Developer's Manual, section 9.1.2.1)
|
||||||
*/
|
*/
|
||||||
|
local_irq_save(flags);
|
||||||
GAFR |= GPIO_32_768kHz;
|
GAFR |= GPIO_32_768kHz;
|
||||||
GPDR |= GPIO_32_768kHz;
|
GPDR |= GPIO_32_768kHz;
|
||||||
TUCR = TUCR_3_6864MHz;
|
local_irq_restore(flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clk_gpio27_disable(struct clk *clk)
|
static void clk_gpio27_disable(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
TUCR = 0;
|
unsigned long flags;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
GPDR &= ~GPIO_32_768kHz;
|
GPDR &= ~GPIO_32_768kHz;
|
||||||
GAFR &= ~GPIO_32_768kHz;
|
GAFR &= ~GPIO_32_768kHz;
|
||||||
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clk_cpu_enable(struct clk *clk)
|
static const struct clk_ops clk_gpio27_ops = {
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clk_cpu_disable(struct clk *clk)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long clk_cpu_get_rate(struct clk *clk)
|
|
||||||
{
|
|
||||||
return sa11x0_getspeed(0) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int clk_enable(struct clk *clk)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (clk) {
|
|
||||||
spin_lock_irqsave(&clocks_lock, flags);
|
|
||||||
if (clk->enabled++ == 0)
|
|
||||||
clk->ops->enable(clk);
|
|
||||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(clk_enable);
|
|
||||||
|
|
||||||
void clk_disable(struct clk *clk)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (clk) {
|
|
||||||
WARN_ON(clk->enabled == 0);
|
|
||||||
spin_lock_irqsave(&clocks_lock, flags);
|
|
||||||
if (--clk->enabled == 0)
|
|
||||||
clk->ops->disable(clk);
|
|
||||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(clk_disable);
|
|
||||||
|
|
||||||
unsigned long clk_get_rate(struct clk *clk)
|
|
||||||
{
|
|
||||||
if (clk && clk->ops && clk->ops->get_rate)
|
|
||||||
return clk->ops->get_rate(clk);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(clk_get_rate);
|
|
||||||
|
|
||||||
const struct clkops clk_gpio27_ops = {
|
|
||||||
.enable = clk_gpio27_enable,
|
.enable = clk_gpio27_enable,
|
||||||
.disable = clk_gpio27_disable,
|
.disable = clk_gpio27_disable,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct clkops clk_cpu_ops = {
|
static const char * const clk_gpio27_parents[] = {
|
||||||
.enable = clk_cpu_enable,
|
"tucr-mux",
|
||||||
.disable = clk_cpu_disable,
|
|
||||||
.get_rate = clk_cpu_get_rate,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_CLK(gpio27, &clk_gpio27_ops);
|
static const struct clk_init_data clk_gpio27_init_data __initconst = {
|
||||||
|
.name = "gpio27",
|
||||||
|
.ops = &clk_gpio27_ops,
|
||||||
|
.parent_names = clk_gpio27_parents,
|
||||||
|
.num_parents = ARRAY_SIZE(clk_gpio27_parents),
|
||||||
|
};
|
||||||
|
|
||||||
static DEFINE_CLK(cpu, &clk_cpu_ops);
|
/*
|
||||||
|
* Derived from the table 8-1 in the SA1110 manual, the MPLL appears to
|
||||||
static unsigned long clk_36864_get_rate(struct clk *clk)
|
* multiply its input rate by 4 x (4 + PPCR). This calculation gives
|
||||||
|
* the exact rate. The figures given in the table are the rates rounded
|
||||||
|
* to 100kHz. Stick with sa11x0_getspeed() for the time being.
|
||||||
|
*/
|
||||||
|
static unsigned long clk_mpll_recalc_rate(struct clk_hw *hw,
|
||||||
|
unsigned long prate)
|
||||||
{
|
{
|
||||||
return 3686400;
|
return sa11x0_getspeed(0) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct clkops clk_36864_ops = {
|
static const struct clk_ops clk_mpll_ops = {
|
||||||
.enable = clk_cpu_enable,
|
.recalc_rate = clk_mpll_recalc_rate,
|
||||||
.disable = clk_cpu_disable,
|
|
||||||
.get_rate = clk_36864_get_rate,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_CLK(36864, &clk_36864_ops);
|
static const char * const clk_mpll_parents[] = {
|
||||||
|
"clk3686400",
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_lookup sa11xx_clkregs[] = {
|
static const struct clk_init_data clk_mpll_init_data __initconst = {
|
||||||
CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27),
|
.name = "mpll",
|
||||||
CLKDEV_INIT("sa1100-rtc", NULL, NULL),
|
.ops = &clk_mpll_ops,
|
||||||
CLKDEV_INIT("sa11x0-fb", NULL, &clk_cpu),
|
.parent_names = clk_mpll_parents,
|
||||||
CLKDEV_INIT("sa11x0-pcmcia", NULL, &clk_cpu),
|
.num_parents = ARRAY_SIZE(clk_mpll_parents),
|
||||||
CLKDEV_INIT("sa11x0-pcmcia.0", NULL, &clk_cpu),
|
.flags = CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL,
|
||||||
CLKDEV_INIT("sa11x0-pcmcia.1", NULL, &clk_cpu),
|
|
||||||
/* sa1111 names devices using internal offsets, PCMCIA is at 0x1800 */
|
|
||||||
CLKDEV_INIT("1800", NULL, &clk_cpu),
|
|
||||||
CLKDEV_INIT(NULL, "OSTIMER0", &clk_36864),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int __init sa11xx_clk_init(void)
|
int __init sa11xx_clk_init(void)
|
||||||
{
|
{
|
||||||
clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
|
struct clk_hw *hw;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
hw = clk_hw_register_fixed_rate(NULL, "clk32768", NULL, 0, 32768);
|
||||||
|
if (IS_ERR(hw))
|
||||||
|
return PTR_ERR(hw);
|
||||||
|
|
||||||
|
clk_hw_register_clkdev(hw, NULL, "sa1100-rtc");
|
||||||
|
|
||||||
|
hw = clk_hw_register_fixed_rate(NULL, "clk3686400", NULL, 0, 3686400);
|
||||||
|
if (IS_ERR(hw))
|
||||||
|
return PTR_ERR(hw);
|
||||||
|
|
||||||
|
clk_hw_register_clkdev(hw, "OSTIMER0", NULL);
|
||||||
|
|
||||||
|
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
|
||||||
|
if (!hw)
|
||||||
|
return -ENOMEM;
|
||||||
|
hw->init = &clk_mpll_init_data;
|
||||||
|
ret = clk_hw_register(NULL, hw);
|
||||||
|
if (ret) {
|
||||||
|
kfree(hw);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_hw_register_clkdev(hw, NULL, "sa11x0-fb");
|
||||||
|
clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia");
|
||||||
|
clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.0");
|
||||||
|
clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.1");
|
||||||
|
clk_hw_register_clkdev(hw, NULL, "1800");
|
||||||
|
|
||||||
|
hw = clk_hw_register_mux(NULL, "tucr-mux", clk_tucr_parents,
|
||||||
|
ARRAY_SIZE(clk_tucr_parents), 0,
|
||||||
|
(void __iomem *)&TUCR, FShft(TUCR_TSEL),
|
||||||
|
FAlnMsk(TUCR_TSEL), 0, &tucr_lock);
|
||||||
|
clk_set_rate(hw->clk, 3686400);
|
||||||
|
|
||||||
|
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
|
||||||
|
if (!hw)
|
||||||
|
return -ENOMEM;
|
||||||
|
hw->init = &clk_gpio27_init_data;
|
||||||
|
ret = clk_hw_register(NULL, hw);
|
||||||
|
if (ret) {
|
||||||
|
kfree(hw);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_hw_register_clkdev(hw, NULL, "sa1111.0");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,57 +87,6 @@ static struct resource h3xxx_flash_resource =
|
||||||
/*
|
/*
|
||||||
* H3xxx uart support
|
* H3xxx uart support
|
||||||
*/
|
*/
|
||||||
static struct gpio h3xxx_uart_gpio[] = {
|
|
||||||
{ H3XXX_GPIO_COM_DCD, GPIOF_IN, "COM DCD" },
|
|
||||||
{ H3XXX_GPIO_COM_CTS, GPIOF_IN, "COM CTS" },
|
|
||||||
{ H3XXX_GPIO_COM_RTS, GPIOF_OUT_INIT_LOW, "COM RTS" },
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool h3xxx_uart_request_gpios(void)
|
|
||||||
{
|
|
||||||
static bool h3xxx_uart_gpio_ok;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (h3xxx_uart_gpio_ok)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
rc = gpio_request_array(h3xxx_uart_gpio, ARRAY_SIZE(h3xxx_uart_gpio));
|
|
||||||
if (rc)
|
|
||||||
pr_err("h3xxx_uart_request_gpios: error %d\n", rc);
|
|
||||||
else
|
|
||||||
h3xxx_uart_gpio_ok = true;
|
|
||||||
|
|
||||||
return h3xxx_uart_gpio_ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void h3xxx_uart_set_mctrl(struct uart_port *port, u_int mctrl)
|
|
||||||
{
|
|
||||||
if (port->mapbase == _Ser3UTCR0) {
|
|
||||||
if (!h3xxx_uart_request_gpios())
|
|
||||||
return;
|
|
||||||
gpio_set_value(H3XXX_GPIO_COM_RTS, !(mctrl & TIOCM_RTS));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static u_int h3xxx_uart_get_mctrl(struct uart_port *port)
|
|
||||||
{
|
|
||||||
u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
|
|
||||||
|
|
||||||
if (port->mapbase == _Ser3UTCR0) {
|
|
||||||
if (!h3xxx_uart_request_gpios())
|
|
||||||
return ret;
|
|
||||||
/*
|
|
||||||
* DCD and CTS bits are inverted in GPLR by RS232 transceiver
|
|
||||||
*/
|
|
||||||
if (gpio_get_value(H3XXX_GPIO_COM_DCD))
|
|
||||||
ret &= ~TIOCM_CD;
|
|
||||||
if (gpio_get_value(H3XXX_GPIO_COM_CTS))
|
|
||||||
ret &= ~TIOCM_CTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void h3xxx_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
|
static void h3xxx_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
|
||||||
{
|
{
|
||||||
if (port->mapbase == _Ser3UTCR0) {
|
if (port->mapbase == _Ser3UTCR0) {
|
||||||
|
@ -170,12 +119,20 @@ static int h3xxx_uart_set_wake(struct uart_port *port, u_int enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sa1100_port_fns h3xxx_port_fns __initdata = {
|
static struct sa1100_port_fns h3xxx_port_fns __initdata = {
|
||||||
.set_mctrl = h3xxx_uart_set_mctrl,
|
|
||||||
.get_mctrl = h3xxx_uart_get_mctrl,
|
|
||||||
.pm = h3xxx_uart_pm,
|
.pm = h3xxx_uart_pm,
|
||||||
.set_wake = h3xxx_uart_set_wake,
|
.set_wake = h3xxx_uart_set_wake,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table h3xxx_uart3_gpio_table = {
|
||||||
|
.dev_id = "sa11x0-uart.3",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_DCD, "dcd", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_CTS, "cts", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_RTS, "rts", GPIO_ACTIVE_LOW),
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EGPIO
|
* EGPIO
|
||||||
*/
|
*/
|
||||||
|
@ -283,6 +240,7 @@ static struct gpiod_lookup_table h3xxx_pcmcia_gpio_table = {
|
||||||
void __init h3xxx_mach_init(void)
|
void __init h3xxx_mach_init(void)
|
||||||
{
|
{
|
||||||
gpiod_add_lookup_table(&h3xxx_pcmcia_gpio_table);
|
gpiod_add_lookup_table(&h3xxx_pcmcia_gpio_table);
|
||||||
|
gpiod_add_lookup_table(&h3xxx_uart3_gpio_table);
|
||||||
sa1100_register_uart_fns(&h3xxx_port_fns);
|
sa1100_register_uart_fns(&h3xxx_port_fns);
|
||||||
sa11x0_register_mtd(&h3xxx_flash_data, &h3xxx_flash_resource, 1);
|
sa11x0_register_mtd(&h3xxx_flash_data, &h3xxx_flash_resource, 1);
|
||||||
platform_add_devices(h3xxx_devices, ARRAY_SIZE(h3xxx_devices));
|
platform_add_devices(h3xxx_devices, ARRAY_SIZE(h3xxx_devices));
|
||||||
|
|
|
@ -49,8 +49,6 @@
|
||||||
/* init funcs */
|
/* init funcs */
|
||||||
static void __init hackkit_map_io(void);
|
static void __init hackkit_map_io(void);
|
||||||
|
|
||||||
static u_int hackkit_get_mctrl(struct uart_port *port);
|
|
||||||
static void hackkit_set_mctrl(struct uart_port *port, u_int mctrl);
|
|
||||||
static void hackkit_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
|
static void hackkit_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
@ -71,8 +69,6 @@ static struct map_desc hackkit_io_desc[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct sa1100_port_fns hackkit_port_fns __initdata = {
|
static struct sa1100_port_fns hackkit_port_fns __initdata = {
|
||||||
.set_mctrl = hackkit_set_mctrl,
|
|
||||||
.get_mctrl = hackkit_get_mctrl,
|
|
||||||
.pm = hackkit_uart_pm,
|
.pm = hackkit_uart_pm,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,50 +101,6 @@ static void hackkit_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
|
||||||
/* TODO: switch on/off uart in powersave mode */
|
/* TODO: switch on/off uart in powersave mode */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Note! this can be called from IRQ context.
|
|
||||||
* FIXME: No modem ctrl lines yet.
|
|
||||||
*/
|
|
||||||
static void hackkit_set_mctrl(struct uart_port *port, u_int mctrl)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
if (port->mapbase == _Ser1UTCR0) {
|
|
||||||
u_int set = 0, clear = 0;
|
|
||||||
|
|
||||||
if (mctrl & TIOCM_RTS)
|
|
||||||
set |= PT_CTRL2_RS1_RTS;
|
|
||||||
else
|
|
||||||
clear |= PT_CTRL2_RS1_RTS;
|
|
||||||
|
|
||||||
if (mctrl & TIOCM_DTR)
|
|
||||||
set |= PT_CTRL2_RS1_DTR;
|
|
||||||
else
|
|
||||||
clear |= PT_CTRL2_RS1_DTR;
|
|
||||||
|
|
||||||
PTCTRL2_clear(clear);
|
|
||||||
PTCTRL2_set(set);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static u_int hackkit_get_mctrl(struct uart_port *port)
|
|
||||||
{
|
|
||||||
u_int ret = 0;
|
|
||||||
#if 0
|
|
||||||
u_int irqsr = PT_IRQSR;
|
|
||||||
|
|
||||||
/* need 2 reads to read current value */
|
|
||||||
irqsr = PT_IRQSR;
|
|
||||||
|
|
||||||
/* TODO: check IRQ source register for modem/com
|
|
||||||
status lines and set them correctly. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mtd_partition hackkit_partitions[] = {
|
static struct mtd_partition hackkit_partitions[] = {
|
||||||
{
|
{
|
||||||
.name = "BLOB",
|
.name = "BLOB",
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_data/sa11x0-serial.h>
|
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
@ -49,23 +48,8 @@
|
||||||
#define IRR_SA1111 (1 << 2)
|
#define IRR_SA1111 (1 << 2)
|
||||||
|
|
||||||
#define NCR_NGPIO 7
|
#define NCR_NGPIO 7
|
||||||
|
|
||||||
#define MDM_CTL0_RTS1 (1 << 0)
|
|
||||||
#define MDM_CTL0_DTR1 (1 << 1)
|
|
||||||
#define MDM_CTL0_RTS2 (1 << 2)
|
|
||||||
#define MDM_CTL0_DTR2 (1 << 3)
|
|
||||||
#define MDM_CTL0_NGPIO 4
|
#define MDM_CTL0_NGPIO 4
|
||||||
|
|
||||||
#define MDM_CTL1_CTS1 (1 << 0)
|
|
||||||
#define MDM_CTL1_DSR1 (1 << 1)
|
|
||||||
#define MDM_CTL1_DCD1 (1 << 2)
|
|
||||||
#define MDM_CTL1_CTS2 (1 << 3)
|
|
||||||
#define MDM_CTL1_DSR2 (1 << 4)
|
|
||||||
#define MDM_CTL1_DCD2 (1 << 5)
|
|
||||||
#define MDM_CTL1_NGPIO 6
|
#define MDM_CTL1_NGPIO 6
|
||||||
|
|
||||||
#define AUD_SEL_1341 (1 << 0)
|
|
||||||
#define AUD_MUTE_1341 (1 << 1)
|
|
||||||
#define AUD_NGPIO 2
|
#define AUD_NGPIO 2
|
||||||
|
|
||||||
extern void sa1110_mb_disable(void);
|
extern void sa1110_mb_disable(void);
|
||||||
|
@ -97,6 +81,30 @@ struct neponset_drvdata {
|
||||||
struct gpio_chip *gpio[4];
|
struct gpio_chip *gpio[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table neponset_uart1_gpio_table = {
|
||||||
|
.dev_id = "sa11x0-uart.1",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl0", 2, "rts", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl0", 3, "dtr", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl1", 3, "cts", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl1", 4, "dsr", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl1", 5, "dcd", GPIO_ACTIVE_LOW),
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table neponset_uart3_gpio_table = {
|
||||||
|
.dev_id = "sa11x0-uart.3",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl0", 0, "rts", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl0", 1, "dtr", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl1", 0, "cts", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl1", 1, "dsr", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("neponset-mdm-ctl1", 2, "dcd", GPIO_ACTIVE_LOW),
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static struct gpiod_lookup_table neponset_pcmcia_table = {
|
static struct gpiod_lookup_table neponset_pcmcia_table = {
|
||||||
.dev_id = "1800",
|
.dev_id = "1800",
|
||||||
.table = {
|
.table = {
|
||||||
|
@ -124,69 +132,6 @@ void neponset_ncr_frob(unsigned int mask, unsigned int val)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(neponset_ncr_frob);
|
EXPORT_SYMBOL(neponset_ncr_frob);
|
||||||
|
|
||||||
static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
|
|
||||||
{
|
|
||||||
struct neponset_drvdata *n = nep;
|
|
||||||
unsigned long mask, val = 0;
|
|
||||||
|
|
||||||
if (!n)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (port->mapbase == _Ser1UTCR0) {
|
|
||||||
mask = MDM_CTL0_RTS2 | MDM_CTL0_DTR2;
|
|
||||||
|
|
||||||
if (!(mctrl & TIOCM_RTS))
|
|
||||||
val |= MDM_CTL0_RTS2;
|
|
||||||
|
|
||||||
if (!(mctrl & TIOCM_DTR))
|
|
||||||
val |= MDM_CTL0_DTR2;
|
|
||||||
} else if (port->mapbase == _Ser3UTCR0) {
|
|
||||||
mask = MDM_CTL0_RTS1 | MDM_CTL0_DTR1;
|
|
||||||
|
|
||||||
if (!(mctrl & TIOCM_RTS))
|
|
||||||
val |= MDM_CTL0_RTS1;
|
|
||||||
|
|
||||||
if (!(mctrl & TIOCM_DTR))
|
|
||||||
val |= MDM_CTL0_DTR1;
|
|
||||||
}
|
|
||||||
|
|
||||||
n->gpio[1]->set_multiple(n->gpio[1], &mask, &val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u_int neponset_get_mctrl(struct uart_port *port)
|
|
||||||
{
|
|
||||||
void __iomem *base = nep->base;
|
|
||||||
u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
|
|
||||||
u_int mdm_ctl1;
|
|
||||||
|
|
||||||
if (!base)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
mdm_ctl1 = readb_relaxed(base + MDM_CTL_1);
|
|
||||||
if (port->mapbase == _Ser1UTCR0) {
|
|
||||||
if (mdm_ctl1 & MDM_CTL1_DCD2)
|
|
||||||
ret &= ~TIOCM_CD;
|
|
||||||
if (mdm_ctl1 & MDM_CTL1_CTS2)
|
|
||||||
ret &= ~TIOCM_CTS;
|
|
||||||
if (mdm_ctl1 & MDM_CTL1_DSR2)
|
|
||||||
ret &= ~TIOCM_DSR;
|
|
||||||
} else if (port->mapbase == _Ser3UTCR0) {
|
|
||||||
if (mdm_ctl1 & MDM_CTL1_DCD1)
|
|
||||||
ret &= ~TIOCM_CD;
|
|
||||||
if (mdm_ctl1 & MDM_CTL1_CTS1)
|
|
||||||
ret &= ~TIOCM_CTS;
|
|
||||||
if (mdm_ctl1 & MDM_CTL1_DSR1)
|
|
||||||
ret &= ~TIOCM_DSR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct sa1100_port_fns neponset_port_fns = {
|
|
||||||
.set_mctrl = neponset_set_mctrl,
|
|
||||||
.get_mctrl = neponset_get_mctrl,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install handler for Neponset IRQ. Note that we have to loop here
|
* Install handler for Neponset IRQ. Note that we have to loop here
|
||||||
* since the ETHERNET and USAR IRQs are level based, and we need to
|
* since the ETHERNET and USAR IRQs are level based, and we need to
|
||||||
|
@ -388,6 +333,8 @@ static int neponset_probe(struct platform_device *dev)
|
||||||
d->base + AUD_CTL, AUD_NGPIO, false,
|
d->base + AUD_CTL, AUD_NGPIO, false,
|
||||||
neponset_aud_names);
|
neponset_aud_names);
|
||||||
|
|
||||||
|
gpiod_add_lookup_table(&neponset_uart1_gpio_table);
|
||||||
|
gpiod_add_lookup_table(&neponset_uart3_gpio_table);
|
||||||
gpiod_add_lookup_table(&neponset_pcmcia_table);
|
gpiod_add_lookup_table(&neponset_pcmcia_table);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -402,8 +349,6 @@ static int neponset_probe(struct platform_device *dev)
|
||||||
d->irq_base, d->irq_base + NEP_IRQ_NR - 1);
|
d->irq_base, d->irq_base + NEP_IRQ_NR - 1);
|
||||||
nep = d;
|
nep = d;
|
||||||
|
|
||||||
sa1100_register_uart_fns(&neponset_port_fns);
|
|
||||||
|
|
||||||
/* Ensure that the memory bus request/grant signals are setup */
|
/* Ensure that the memory bus request/grant signals are setup */
|
||||||
sa1110_mb_disable();
|
sa1110_mb_disable();
|
||||||
|
|
||||||
|
@ -442,6 +387,8 @@ static int neponset_remove(struct platform_device *dev)
|
||||||
platform_device_unregister(d->smc91x);
|
platform_device_unregister(d->smc91x);
|
||||||
|
|
||||||
gpiod_remove_lookup_table(&neponset_pcmcia_table);
|
gpiod_remove_lookup_table(&neponset_pcmcia_table);
|
||||||
|
gpiod_remove_lookup_table(&neponset_uart3_gpio_table);
|
||||||
|
gpiod_remove_lookup_table(&neponset_uart1_gpio_table);
|
||||||
|
|
||||||
irq_set_chained_handler(irq, NULL);
|
irq_set_chained_handler(irq, NULL);
|
||||||
irq_free_descs(d->irq_base, NEP_IRQ_NR);
|
irq_free_descs(d->irq_base, NEP_IRQ_NR);
|
||||||
|
|
|
@ -511,6 +511,7 @@ config SERIAL_SA1100
|
||||||
bool "SA1100 serial port support"
|
bool "SA1100 serial port support"
|
||||||
depends on ARCH_SA1100
|
depends on ARCH_SA1100
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
|
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||||
help
|
help
|
||||||
If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
|
If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
|
||||||
can enable its onboard serial port by enabling this option.
|
can enable its onboard serial port by enabling this option.
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <mach/irqs.h>
|
#include <mach/irqs.h>
|
||||||
|
|
||||||
|
#include "serial_mctrl_gpio.h"
|
||||||
|
|
||||||
/* We've been assigned a range on the "Low-density serial ports" major */
|
/* We've been assigned a range on the "Low-density serial ports" major */
|
||||||
#define SERIAL_SA1100_MAJOR 204
|
#define SERIAL_SA1100_MAJOR 204
|
||||||
#define MINOR_START 5
|
#define MINOR_START 5
|
||||||
|
@ -77,6 +79,7 @@ struct sa1100_port {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
unsigned int old_status;
|
unsigned int old_status;
|
||||||
|
struct mctrl_gpios *gpios;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -174,6 +177,8 @@ static void sa1100_enable_ms(struct uart_port *port)
|
||||||
container_of(port, struct sa1100_port, port);
|
container_of(port, struct sa1100_port, port);
|
||||||
|
|
||||||
mod_timer(&sport->timer, jiffies);
|
mod_timer(&sport->timer, jiffies);
|
||||||
|
|
||||||
|
mctrl_gpio_enable_ms(sport->gpios);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -322,11 +327,21 @@ static unsigned int sa1100_tx_empty(struct uart_port *port)
|
||||||
|
|
||||||
static unsigned int sa1100_get_mctrl(struct uart_port *port)
|
static unsigned int sa1100_get_mctrl(struct uart_port *port)
|
||||||
{
|
{
|
||||||
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
struct sa1100_port *sport =
|
||||||
|
container_of(port, struct sa1100_port, port);
|
||||||
|
int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||||
|
|
||||||
|
mctrl_gpio_get(sport->gpios, &ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
{
|
{
|
||||||
|
struct sa1100_port *sport =
|
||||||
|
container_of(port, struct sa1100_port, port);
|
||||||
|
|
||||||
|
mctrl_gpio_set(sport->gpios, mctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -842,6 +857,31 @@ static int sa1100_serial_resume(struct platform_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sa1100_serial_add_one_port(struct sa1100_port *sport, struct platform_device *dev)
|
||||||
|
{
|
||||||
|
sport->port.dev = &dev->dev;
|
||||||
|
|
||||||
|
// mctrl_gpio_init() requires that the GPIO driver supports interrupts,
|
||||||
|
// but we need to support GPIO drivers for hardware that has no such
|
||||||
|
// interrupts. Use mctrl_gpio_init_noauto() instead.
|
||||||
|
sport->gpios = mctrl_gpio_init_noauto(sport->port.dev, 0);
|
||||||
|
if (IS_ERR(sport->gpios)) {
|
||||||
|
int err = PTR_ERR(sport->gpios);
|
||||||
|
|
||||||
|
dev_err(sport->port.dev, "failed to get mctrl gpios: %d\n",
|
||||||
|
err);
|
||||||
|
|
||||||
|
if (err == -EPROBE_DEFER)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
sport->gpios = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
platform_set_drvdata(dev, sport);
|
||||||
|
|
||||||
|
return uart_add_one_port(&sa1100_reg, &sport->port);
|
||||||
|
}
|
||||||
|
|
||||||
static int sa1100_serial_probe(struct platform_device *dev)
|
static int sa1100_serial_probe(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
struct resource *res = dev->resource;
|
struct resource *res = dev->resource;
|
||||||
|
@ -856,9 +896,7 @@ static int sa1100_serial_probe(struct platform_device *dev)
|
||||||
if (sa1100_ports[i].port.mapbase != res->start)
|
if (sa1100_ports[i].port.mapbase != res->start)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sa1100_ports[i].port.dev = &dev->dev;
|
sa1100_serial_add_one_port(&sa1100_ports[i], dev);
|
||||||
uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
|
|
||||||
platform_set_drvdata(dev, &sa1100_ports[i]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue