Merge branch 'for-next/clps711x'
This commit is contained in:
commit
7845fd7af6
|
@ -39,7 +39,11 @@ config ARCH_BCM2835
|
|||
config ARCH_CLPS711X
|
||||
bool "Cirrus Logic EP711x/EP721x/EP731x"
|
||||
select CLKDEV_LOOKUP
|
||||
select CLOCKSOURCE_CLPS711X
|
||||
select COMMON_CLK
|
||||
select CPU_32v4T
|
||||
select GPIOLIB
|
||||
select MFD_SYSCON
|
||||
|
||||
config ARCH_EP93XX
|
||||
bool "Cirrus Logic EP93xx"
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
global.hostname=clps711x
|
||||
|
||||
# set to false if you do not want to have colors
|
||||
global.allow_color=true
|
||||
|
||||
# user (used for network filenames)
|
||||
global.user=anonymous
|
||||
|
||||
# timeout in seconds before the default boot entry is started
|
||||
global.autoboot_timeout=2
|
||||
|
||||
# default boot entry (one of /env/boot/*)
|
||||
if [ -e /dev/nor0 ]; then
|
||||
global.boot.default=nor
|
||||
fi
|
||||
|
||||
# default bootargs
|
||||
global.linux.bootargs.base="earlyprintk console=ttyCL0,57600n8"
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
|
||||
global.hostname=clps711x
|
||||
|
||||
# Timeout in seconds before the default boot entry is started
|
||||
global.autoboot_timeout=2
|
||||
|
||||
# Default boot entry (one of /env/boot/*)
|
||||
if [ -e /dev/nor0 ]; then
|
||||
global.boot.default=nor
|
||||
fi
|
||||
|
||||
# Board bootargs
|
||||
global.linux.bootargs.base="earlyprintk console=ttyCL0,57600n8"
|
|
@ -14,13 +14,15 @@
|
|||
|
||||
#include <mach/clps711x.h>
|
||||
|
||||
#if (CONFIG_CLPS711X_CPU_PLL_MULT < 20) || (CONFIG_CLPS711X_CPU_PLL_MULT > 50)
|
||||
# error "CPU PLL multiplier out of range"
|
||||
#ifdef CONFIG_CLPS711X_RAISE_CPUFREQ
|
||||
# define CLPS711X_CPU_PLL_MULT 50
|
||||
#else
|
||||
# define CLPS711X_CPU_PLL_MULT 40
|
||||
#endif
|
||||
|
||||
void __naked __bare_init barebox_arm_reset_vector(void)
|
||||
{
|
||||
arm_cpu_lowlevel_init();
|
||||
|
||||
clps711x_barebox_entry(CONFIG_CLPS711X_CPU_PLL_MULT);
|
||||
clps711x_barebox_entry(CLPS711X_CPU_PLL_MULT);
|
||||
}
|
||||
|
|
|
@ -12,14 +12,13 @@ endchoice
|
|||
|
||||
menu "CLPS711X specific settings"
|
||||
|
||||
config CLPS711X_CPU_PLL_MULT
|
||||
int "CPU PLL multiplier (20-50)"
|
||||
range 20 50
|
||||
default "40"
|
||||
config CLPS711X_RAISE_CPUFREQ
|
||||
bool "Raise CPU frequency to 90 MHz"
|
||||
depends on MACH_CLEP7212
|
||||
help
|
||||
Define CPU PLL multiplier. PLL is calculated by formula:
|
||||
PLL Frequency = (PLL Multiplier / 2) * 3686400 Hz
|
||||
Default value is 40, for achieve 73 MHz.
|
||||
Raise CPU frequency to 90 MHz. This operation can be performed
|
||||
only for devices which allow to operate at 90 MHz.
|
||||
If option is not selected, CPU frequency will set to default 73 MHz.
|
||||
|
||||
endmenu
|
||||
|
||||
|
|
|
@ -9,103 +9,119 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <clock.h>
|
||||
#include <sizes.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/clps711x.h>
|
||||
|
||||
static struct clk {
|
||||
unsigned long rate;
|
||||
} uart_clk, bus_clk;
|
||||
#define CLPS711X_OSC_FREQ 3686400
|
||||
#define CLPS711X_EXT_FREQ 13000000
|
||||
|
||||
static uint64_t clocksource_read(void)
|
||||
{
|
||||
return ~readw(TC2D);
|
||||
}
|
||||
|
||||
static struct clocksource cs = {
|
||||
.read = clocksource_read,
|
||||
.mask = CLOCKSOURCE_MASK(16),
|
||||
enum clps711x_clks {
|
||||
dummy, cpu, bus, uart, timer_hf, timer_lf, tc1, tc2, clk_max
|
||||
};
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
return clk->rate;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
static struct {
|
||||
const char *name;
|
||||
struct clk *clk;
|
||||
} clks[clk_max] = {
|
||||
{ "dummy", },
|
||||
{ "cpu", },
|
||||
{ "bus", },
|
||||
{ "uart", },
|
||||
{ "timer_hf", },
|
||||
{ "timer_lf", },
|
||||
{ "tc1", },
|
||||
{ "tc2", },
|
||||
};
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
/* Do nothing */
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_enable);
|
||||
static const char *tc_sel_clks[] = {
|
||||
"timer_lf",
|
||||
"timer_hf",
|
||||
};
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
static __init void clps711x_clk_register(enum clps711x_clks id)
|
||||
{
|
||||
/* Do nothing */
|
||||
clk_register_clkdev(clks[id].clk, clks[id].name, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
static int clocks_init(void)
|
||||
static __init int clps711x_clk_init(void)
|
||||
{
|
||||
int osc, ext, pll, cpu, timer;
|
||||
unsigned int f_cpu, f_bus, f_uart, f_timer_hf, f_timer_lf, pll;
|
||||
u32 tmp;
|
||||
|
||||
osc = 3686400;
|
||||
ext = 13000000;
|
||||
|
||||
tmp = readl(PLLR) >> 24;
|
||||
if (tmp)
|
||||
pll = (osc * tmp) / 2;
|
||||
pll = (CLPS711X_OSC_FREQ * tmp) / 2;
|
||||
else
|
||||
pll = 73728000; /* Default value for old CPUs */
|
||||
|
||||
tmp = readl(SYSFLG2);
|
||||
if (tmp & SYSFLG2_CKMODE) {
|
||||
cpu = ext;
|
||||
bus_clk.rate = cpu;
|
||||
f_cpu = CLPS711X_EXT_FREQ;
|
||||
f_bus = CLPS711X_EXT_FREQ;
|
||||
} else {
|
||||
cpu = pll;
|
||||
if (cpu >= 36864000)
|
||||
bus_clk.rate = cpu / 2;
|
||||
f_cpu = pll;
|
||||
if (f_cpu >= 36864000)
|
||||
f_bus = f_cpu / 2;
|
||||
else
|
||||
bus_clk.rate = 36864000 / 2;
|
||||
f_bus = 36864000 / 2;
|
||||
}
|
||||
|
||||
uart_clk.rate = bus_clk.rate / 10;
|
||||
f_uart = f_bus / 10;
|
||||
|
||||
if (tmp & SYSFLG2_CKMODE) {
|
||||
tmp = readw(SYSCON2);
|
||||
if (tmp & SYSCON2_OSTB)
|
||||
timer = ext / 26;
|
||||
f_timer_hf = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 26);
|
||||
else
|
||||
timer = 541440;
|
||||
f_timer_hf = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 24);
|
||||
} else
|
||||
timer = cpu / 144;
|
||||
f_timer_hf = DIV_ROUND_CLOSEST(f_cpu, 144);
|
||||
|
||||
f_timer_lf = DIV_ROUND_CLOSEST(f_timer_hf, 256);
|
||||
|
||||
/* Turn timers in free running mode */
|
||||
tmp = readl(SYSCON1);
|
||||
tmp &= ~SYSCON1_TC2M; /* Free running mode */
|
||||
tmp |= SYSCON1_TC2S; /* High frequency source */
|
||||
tmp &= ~(SYSCON1_TC1M | SYSCON1_TC2M);
|
||||
writel(tmp, SYSCON1);
|
||||
|
||||
clocks_calc_mult_shift(&cs.mult, &cs.shift, timer, NSEC_PER_SEC, 10);
|
||||
clks[dummy].clk = clk_fixed(clks[dummy].name, 0);
|
||||
clks[cpu].clk = clk_fixed(clks[cpu].name, f_cpu);
|
||||
clks[bus].clk = clk_fixed(clks[bus].name, f_bus);
|
||||
clks[uart].clk = clk_fixed(clks[uart].name, f_uart);
|
||||
clks[timer_hf].clk = clk_fixed(clks[timer_hf].name, f_timer_hf);
|
||||
clks[timer_lf].clk = clk_fixed(clks[timer_lf].name, f_timer_lf);
|
||||
clks[tc1].clk = clk_mux(clks[tc1].name, IOMEM(SYSCON1), 5, 1,
|
||||
tc_sel_clks, ARRAY_SIZE(tc_sel_clks));
|
||||
clks[tc2].clk = clk_mux(clks[tc2].name, IOMEM(SYSCON1), 7, 1,
|
||||
tc_sel_clks, ARRAY_SIZE(tc_sel_clks));
|
||||
|
||||
return init_clock(&cs);
|
||||
}
|
||||
core_initcall(clocks_init);
|
||||
|
||||
static struct clk_lookup clocks_lookups[] = {
|
||||
CLKDEV_CON_ID("bus", &bus_clk),
|
||||
CLKDEV_DEV_ID("clps711x_serial0", &uart_clk),
|
||||
CLKDEV_DEV_ID("clps711x_serial1", &uart_clk),
|
||||
};
|
||||
|
||||
static int clkdev_init(void)
|
||||
{
|
||||
clkdev_add_table(clocks_lookups, ARRAY_SIZE(clocks_lookups));
|
||||
clps711x_clk_register(dummy);
|
||||
clps711x_clk_register(cpu);
|
||||
clps711x_clk_register(bus);
|
||||
clps711x_clk_register(uart);
|
||||
clps711x_clk_register(timer_hf);
|
||||
clps711x_clk_register(timer_lf);
|
||||
clps711x_clk_register(tc1);
|
||||
clps711x_clk_register(tc2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(clkdev_init);
|
||||
postcore_initcall(clps711x_clk_init);
|
||||
|
||||
static const char *clps711x_clocksrc_name = "clps711x-cs";
|
||||
|
||||
static __init int clps711x_core_init(void)
|
||||
{
|
||||
/* Using TC2 in low frequency mode as clocksource */
|
||||
clk_set_parent(clks[tc2].clk, clks[timer_lf].clk);
|
||||
clk_add_alias(NULL, clps711x_clocksrc_name, "tc2", NULL);
|
||||
add_generic_device(clps711x_clocksrc_name, DEVICE_ID_SINGLE, NULL,
|
||||
TC2D, SZ_2, IORESOURCE_MEM, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
coredevice_initcall(clps711x_core_init);
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/memory.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <mach/clps711x.h>
|
||||
|
||||
static int clps711x_mem_init(void)
|
||||
|
@ -42,68 +44,92 @@ void clps711x_setup_memcfg(int bank, u32 val)
|
|||
case 0 ... 3:
|
||||
_clps711x_setup_memcfg(bank, MEMCFG1, val);
|
||||
break;
|
||||
case 4 ... 7:
|
||||
case 4 ... 5:
|
||||
_clps711x_setup_memcfg(bank - 4, MEMCFG2, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct resource uart0_resources[] = {
|
||||
{
|
||||
.start = UBRLCR1,
|
||||
.end = UBRLCR1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = SYSCON1,
|
||||
.end = SYSCON1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = SYSFLG1,
|
||||
.end = SYSFLG1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = UARTDR1,
|
||||
.end = UARTDR1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
DEFINE_RES_MEM(UBRLCR1, SZ_4),
|
||||
DEFINE_RES_MEM(UARTDR1, SZ_4),
|
||||
};
|
||||
|
||||
static struct resource uart1_resources[] = {
|
||||
{
|
||||
.start = UBRLCR2,
|
||||
.end = UBRLCR2,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = SYSCON2,
|
||||
.end = SYSCON2,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = SYSFLG2,
|
||||
.end = SYSFLG2,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = UARTDR2,
|
||||
.end = UARTDR2,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
DEFINE_RES_MEM(UBRLCR2, SZ_4),
|
||||
DEFINE_RES_MEM(UARTDR2, SZ_4),
|
||||
};
|
||||
|
||||
void clps711x_add_uart(unsigned int id)
|
||||
{
|
||||
switch (id) {
|
||||
case 0:
|
||||
clk_add_alias(NULL, "clps711x_serial0", "uart", NULL);
|
||||
add_generic_device_res("clps711x_serial", 0, uart0_resources,
|
||||
ARRAY_SIZE(uart0_resources), NULL);
|
||||
break;
|
||||
case 1:
|
||||
clk_add_alias(NULL, "clps711x_serial1", "uart", NULL);
|
||||
add_generic_device_res("clps711x_serial", 1, uart1_resources,
|
||||
ARRAY_SIZE(uart1_resources), NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct resource gpio0_resources[] = {
|
||||
DEFINE_RES_MEM(PADR, SZ_1),
|
||||
DEFINE_RES_MEM(PADDR, SZ_1),
|
||||
};
|
||||
|
||||
static struct resource gpio1_resources[] = {
|
||||
DEFINE_RES_MEM(PBDR, SZ_1),
|
||||
DEFINE_RES_MEM(PBDDR, SZ_1),
|
||||
};
|
||||
|
||||
static struct resource gpio2_resources[] = {
|
||||
DEFINE_RES_MEM(PCDR, SZ_1),
|
||||
DEFINE_RES_MEM(PCDDR, SZ_1),
|
||||
};
|
||||
|
||||
static struct resource gpio3_resources[] = {
|
||||
DEFINE_RES_MEM(PDDR, SZ_1),
|
||||
DEFINE_RES_MEM(PDDDR, SZ_1),
|
||||
};
|
||||
|
||||
static struct resource gpio4_resources[] = {
|
||||
DEFINE_RES_MEM(PEDR, SZ_1),
|
||||
DEFINE_RES_MEM(PEDDR, SZ_1),
|
||||
};
|
||||
|
||||
static __init int clps711x_gpio_init(void)
|
||||
{
|
||||
add_generic_device_res("clps711x-gpio", 0, gpio0_resources,
|
||||
ARRAY_SIZE(gpio0_resources), NULL);
|
||||
add_generic_device_res("clps711x-gpio", 1, gpio1_resources,
|
||||
ARRAY_SIZE(gpio1_resources), NULL);
|
||||
add_generic_device_res("clps711x-gpio", 2, gpio2_resources,
|
||||
ARRAY_SIZE(gpio2_resources), NULL);
|
||||
add_generic_device_res("clps711x-gpio", 3, gpio3_resources,
|
||||
ARRAY_SIZE(gpio3_resources), NULL);
|
||||
add_generic_device_res("clps711x-gpio", 4, gpio4_resources,
|
||||
ARRAY_SIZE(gpio4_resources), NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
coredevice_initcall(clps711x_gpio_init);
|
||||
|
||||
static __init int clps711x_syscon_init(void)
|
||||
{
|
||||
/* SYSCON1, SYSFLG1 */
|
||||
add_generic_device("clps711x-syscon", 1, NULL, SYSCON1, SZ_128,
|
||||
IORESOURCE_MEM, NULL);
|
||||
/* SYSCON2, SYSFLG2 */
|
||||
add_generic_device("clps711x-syscon", 2, NULL, SYSCON2, SZ_128,
|
||||
IORESOURCE_MEM, NULL);
|
||||
/* SYSCON3 */
|
||||
add_generic_device("clps711x-syscon", 3, NULL, SYSCON3, SZ_64,
|
||||
IORESOURCE_MEM, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(clps711x_syscon_init);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#include <asm-generic/gpio.h>
|
||||
|
||||
#define CLPS711X_GPIO(prt,bit) ((prt) * 8 + (bit))
|
|
@ -21,12 +21,12 @@ void __naked __bare_init clps711x_barebox_entry(u32 pllmult)
|
|||
{
|
||||
u32 cpu, bus;
|
||||
|
||||
/* Setup base clocking, Enable SDQM pins */
|
||||
writel(SYSCON3_CLKCTL0 | SYSCON3_CLKCTL1, SYSCON3);
|
||||
asm("nop");
|
||||
|
||||
/* Check if we running from external 13 MHz clock */
|
||||
if (!(readl(SYSFLG2) & SYSFLG2_CKMODE)) {
|
||||
/* Setup bus wait state scaling factor to 2 */
|
||||
writel(SYSCON3_CLKCTL0 | SYSCON3_CLKCTL1, SYSCON3);
|
||||
asm("nop");
|
||||
|
||||
/* Check valid multiplier, default to 74 MHz */
|
||||
if ((pllmult < 20) || (pllmult > 50))
|
||||
pllmult = 40;
|
||||
|
@ -42,11 +42,15 @@ void __naked __bare_init clps711x_barebox_entry(u32 pllmult)
|
|||
cpu = pllmult * 3686400;
|
||||
|
||||
if (cpu >= 36864000)
|
||||
bus = cpu /2;
|
||||
bus = cpu / 2;
|
||||
else
|
||||
bus = 36864000 / 2;
|
||||
} else
|
||||
} else {
|
||||
bus = 13000000;
|
||||
/* Setup bus wait state scaling factor to 1 */
|
||||
writel(0, SYSCON3);
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
/* CLKEN select, SDRAM width=32 */
|
||||
writel(SYSCON2_CLKENSL, SYSCON2);
|
||||
|
|
|
@ -10,6 +10,10 @@ config CLOCKSOURCE_BCM2835
|
|||
bool
|
||||
depends on ARCH_BCM2835
|
||||
|
||||
config CLOCKSOURCE_CLPS711X
|
||||
bool
|
||||
depends on ARCH_CLPS711X
|
||||
|
||||
config CLOCKSOURCE_NOMADIK
|
||||
bool
|
||||
depends on ARM
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
obj-$(CONFIG_AMBA_SP804) += amba-sp804.o
|
||||
obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
|
||||
obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o
|
||||
obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o
|
||||
obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clock.h>
|
||||
#include <io.h>
|
||||
#include <init.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
static __iomem void *clps711x_timer_base;
|
||||
|
||||
static uint64_t clps711x_cs_read(void)
|
||||
{
|
||||
return ~readw(clps711x_timer_base);
|
||||
}
|
||||
|
||||
static struct clocksource clps711x_cs = {
|
||||
.read = clps711x_cs_read,
|
||||
.mask = CLOCKSOURCE_MASK(16),
|
||||
};
|
||||
|
||||
static int clps711x_cs_probe(struct device_d *dev)
|
||||
{
|
||||
u32 rate;
|
||||
struct clk *timer_clk;
|
||||
|
||||
timer_clk = clk_get(dev, NULL);
|
||||
if (IS_ERR(timer_clk))
|
||||
return PTR_ERR(timer_clk);
|
||||
|
||||
rate = clk_get_rate(timer_clk);
|
||||
clps711x_timer_base = dev_request_mem_region(dev, 0);
|
||||
if (!clps711x_timer_base) {
|
||||
clk_put(timer_clk);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
clocks_calc_mult_shift(&clps711x_cs.mult, &clps711x_cs.shift, rate,
|
||||
NSEC_PER_SEC, 10);
|
||||
|
||||
return init_clock(&clps711x_cs);
|
||||
}
|
||||
|
||||
static struct driver_d clps711x_cs_driver = {
|
||||
.name = "clps711x-cs",
|
||||
.probe = clps711x_cs_probe,
|
||||
};
|
||||
|
||||
static __init int clps711x_cs_init(void)
|
||||
{
|
||||
return platform_driver_register(&clps711x_cs_driver);
|
||||
}
|
||||
coredevice_initcall(clps711x_cs_init);
|
|
@ -6,10 +6,27 @@ if GPIOLIB
|
|||
|
||||
menu "GPIO"
|
||||
|
||||
config GPIO_GENERIC
|
||||
bool
|
||||
|
||||
config GPIO_BCM2835
|
||||
bool "GPIO support for BCM2835"
|
||||
depends on ARCH_BCM2835
|
||||
|
||||
config GPIO_CLPS711X
|
||||
bool "GPIO support for CLPS711X"
|
||||
depends on ARCH_CLPS711X
|
||||
select GPIO_GENERIC
|
||||
help
|
||||
Say yes here to enable the GPIO driver for the CLPS711X CPUs
|
||||
|
||||
config GPIO_GENERIC_PLATFORM
|
||||
bool "Generic memory-mapped GPIO controller support"
|
||||
select GPIO_GENERIC
|
||||
help
|
||||
Say yes here to support basic platform memory-mapped
|
||||
GPIO controllers
|
||||
|
||||
config GPIO_PL061
|
||||
bool "PrimeCell PL061 GPIO support"
|
||||
depends on ARM_AMBA
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
obj-$(CONFIG_GPIOLIB) += gpio.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpio.o
|
||||
obj-$(CONFIG_GPIO_BCM2835) += gpio-bcm2835.o
|
||||
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
|
||||
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
|
||||
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
|
||||
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
|
||||
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <linux/basic_mmio_gpio.h>
|
||||
|
||||
static int clps711x_gpio_probe(struct device_d *dev)
|
||||
{
|
||||
int err;
|
||||
void __iomem *dat, *dir = NULL, *dir_inv = NULL;
|
||||
struct bgpio_chip *bgc;
|
||||
|
||||
if ((dev->id < 0) || (dev->id > 4))
|
||||
return -ENODEV;
|
||||
|
||||
dat = dev_request_mem_region(dev, 0);
|
||||
switch (dev->id) {
|
||||
case 3:
|
||||
dir_inv = dev_request_mem_region(dev, 1);
|
||||
break;
|
||||
default:
|
||||
dir = dev_request_mem_region(dev, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dat || (!dir && !dir_inv))
|
||||
return -EINVAL;
|
||||
|
||||
bgc = xzalloc(sizeof(struct bgpio_chip));
|
||||
if (!bgc)
|
||||
return -ENOMEM;
|
||||
|
||||
err = bgpio_init(bgc, dev, 1, dat, NULL, NULL, dir, dir_inv, 0);
|
||||
if (err) {
|
||||
free(bgc);
|
||||
return err;
|
||||
}
|
||||
|
||||
bgc->gc.base = dev->id * 8;
|
||||
switch (dev->id) {
|
||||
case 4:
|
||||
bgc->gc.ngpio = 3;
|
||||
break;
|
||||
default:
|
||||
bgc->gc.ngpio = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
return gpiochip_add(&bgc->gc);
|
||||
}
|
||||
|
||||
static struct driver_d clps711x_gpio_driver = {
|
||||
.name = "clps711x-gpio",
|
||||
.probe = clps711x_gpio_probe,
|
||||
};
|
||||
|
||||
static __init int clps711x_gpio_register(void)
|
||||
{
|
||||
return platform_driver_register(&clps711x_gpio_driver);
|
||||
}
|
||||
coredevice_initcall(clps711x_gpio_register);
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* Generic driver for memory-mapped GPIO controllers.
|
||||
*
|
||||
* Based on linux driver by:
|
||||
* Copyright 2008 MontaVista Software, Inc.
|
||||
* Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
#include <malloc.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/basic_mmio_gpio.h>
|
||||
|
||||
static void bgpio_write8(void __iomem *reg, unsigned int data)
|
||||
{
|
||||
writeb(data, reg);
|
||||
}
|
||||
|
||||
static unsigned int bgpio_read8(void __iomem *reg)
|
||||
{
|
||||
return readb(reg);
|
||||
}
|
||||
|
||||
static void bgpio_write16(void __iomem *reg, unsigned int data)
|
||||
{
|
||||
writew(data, reg);
|
||||
}
|
||||
|
||||
static unsigned int bgpio_read16(void __iomem *reg)
|
||||
{
|
||||
return readw(reg);
|
||||
}
|
||||
|
||||
static void bgpio_write32(void __iomem *reg, unsigned int data)
|
||||
{
|
||||
writel(data, reg);
|
||||
}
|
||||
|
||||
static unsigned int bgpio_read32(void __iomem *reg)
|
||||
{
|
||||
return readl(reg);
|
||||
}
|
||||
|
||||
static unsigned int bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
|
||||
{
|
||||
return 1 << pin;
|
||||
}
|
||||
|
||||
static unsigned int bgpio_pin2mask_be(struct bgpio_chip *bgc, unsigned int pin)
|
||||
{
|
||||
return 1 << (bgc->bits - 1 - pin);
|
||||
}
|
||||
|
||||
static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
|
||||
return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
|
||||
}
|
||||
|
||||
static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
unsigned int mask = bgc->pin2mask(bgc, gpio);
|
||||
|
||||
if (val)
|
||||
bgc->data |= mask;
|
||||
else
|
||||
bgc->data &= ~mask;
|
||||
|
||||
bgc->write_reg(bgc->reg_dat, bgc->data);
|
||||
}
|
||||
|
||||
static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
|
||||
int val)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
unsigned int mask = bgc->pin2mask(bgc, gpio);
|
||||
|
||||
if (val)
|
||||
bgc->write_reg(bgc->reg_set, mask);
|
||||
else
|
||||
bgc->write_reg(bgc->reg_clr, mask);
|
||||
}
|
||||
|
||||
static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
unsigned int mask = bgc->pin2mask(bgc, gpio);
|
||||
|
||||
if (val)
|
||||
bgc->data |= mask;
|
||||
else
|
||||
bgc->data &= ~mask;
|
||||
|
||||
bgc->write_reg(bgc->reg_set, bgc->data);
|
||||
}
|
||||
|
||||
static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
|
||||
int val)
|
||||
{
|
||||
gc->ops->set(gc, gpio, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
|
||||
bgc->dir &= ~bgc->pin2mask(bgc, gpio);
|
||||
bgc->write_reg(bgc->reg_dir, bgc->dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
|
||||
gc->ops->set(gc, gpio, val);
|
||||
|
||||
bgc->dir |= bgc->pin2mask(bgc, gpio);
|
||||
bgc->write_reg(bgc->reg_dir, bgc->dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
|
||||
bgc->dir |= bgc->pin2mask(bgc, gpio);
|
||||
bgc->write_reg(bgc->reg_dir, bgc->dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
|
||||
gc->ops->set(gc, gpio, val);
|
||||
|
||||
bgc->dir &= ~bgc->pin2mask(bgc, gpio);
|
||||
bgc->write_reg(bgc->reg_dir, bgc->dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgpio_setup_accessors(struct device_d *dev, struct bgpio_chip *bgc,
|
||||
bool be)
|
||||
{
|
||||
switch (bgc->bits) {
|
||||
case 8:
|
||||
bgc->read_reg = bgpio_read8;
|
||||
bgc->write_reg = bgpio_write8;
|
||||
break;
|
||||
case 16:
|
||||
bgc->read_reg = bgpio_read16;
|
||||
bgc->write_reg = bgpio_write16;
|
||||
break;
|
||||
case 32:
|
||||
bgc->read_reg = bgpio_read32;
|
||||
bgc->write_reg = bgpio_write32;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Unsupported data width %u bits\n", bgc->bits);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the device and allocate the resources. For setting GPIO's there are
|
||||
* three supported configurations:
|
||||
*
|
||||
* - single input/output register resource (named "dat").
|
||||
* - set/clear pair (named "set" and "clr").
|
||||
* - single output register resource and single input resource ("set" and
|
||||
* dat").
|
||||
*
|
||||
* For the single output register, this drives a 1 by setting a bit and a zero
|
||||
* by clearing a bit. For the set clr pair, this drives a 1 by setting a bit
|
||||
* in the set register and clears it by setting a bit in the clear register.
|
||||
* The configuration is detected by which resources are present.
|
||||
*
|
||||
* For setting the GPIO direction, there are three supported configurations:
|
||||
*
|
||||
* - simple bidirection GPIO that requires no configuration.
|
||||
* - an output direction register (named "dirout") where a 1 bit
|
||||
* indicates the GPIO is an output.
|
||||
* - an input direction register (named "dirin") where a 1 bit indicates
|
||||
* the GPIO is an input.
|
||||
*/
|
||||
static int bgpio_setup_io(struct bgpio_chip *bgc,
|
||||
void __iomem *dat,
|
||||
void __iomem *set,
|
||||
void __iomem *clr)
|
||||
{
|
||||
if (!dat)
|
||||
return -EINVAL;
|
||||
|
||||
bgc->reg_dat = dat;
|
||||
|
||||
if (set && clr) {
|
||||
bgc->reg_set = set;
|
||||
bgc->reg_clr = clr;
|
||||
bgc->gc.ops->set = bgpio_set_with_clear;
|
||||
} else if (set && !clr) {
|
||||
bgc->reg_set = set;
|
||||
bgc->gc.ops->set = bgpio_set_set;
|
||||
} else
|
||||
bgc->gc.ops->set = bgpio_set;
|
||||
|
||||
bgc->gc.ops->get = bgpio_get;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgpio_setup_direction(struct bgpio_chip *bgc,
|
||||
void __iomem *dirout,
|
||||
void __iomem *dirin)
|
||||
{
|
||||
if (dirout && dirin)
|
||||
return -EINVAL;
|
||||
|
||||
if (dirout) {
|
||||
bgc->reg_dir = dirout;
|
||||
bgc->gc.ops->direction_output = bgpio_dir_out;
|
||||
bgc->gc.ops->direction_input = bgpio_dir_in;
|
||||
} else if (dirin) {
|
||||
bgc->reg_dir = dirin;
|
||||
bgc->gc.ops->direction_output = bgpio_dir_out_inv;
|
||||
bgc->gc.ops->direction_input = bgpio_dir_in_inv;
|
||||
} else {
|
||||
bgc->gc.ops->direction_output = bgpio_simple_dir_out;
|
||||
bgc->gc.ops->direction_input = bgpio_simple_dir_in;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bgpio_init(struct bgpio_chip *bgc, struct device_d *dev,
|
||||
unsigned int sz, void __iomem *dat, void __iomem *set,
|
||||
void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
|
||||
unsigned long flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((sz > 4) || !is_power_of_2(sz))
|
||||
return -EINVAL;
|
||||
|
||||
bgc->bits = sz * 8;
|
||||
bgc->gc.ngpio = bgc->bits;
|
||||
bgc->gc.base = -1;
|
||||
bgc->gc.dev = dev;
|
||||
bgc->gc.ops = &bgc->ops;
|
||||
|
||||
ret = bgpio_setup_io(bgc, dat, set, clr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bgpio_setup_accessors(dev, bgc, flags & BGPIOF_BIG_ENDIAN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bgpio_setup_direction(bgc, dirout, dirin);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bgc->data = bgc->read_reg(bgc->reg_dat);
|
||||
|
||||
if (bgc->gc.ops->set == bgpio_set_set && !(flags &
|
||||
BGPIOF_UNREADABLE_REG_SET))
|
||||
bgc->data = bgc->read_reg(bgc->reg_set);
|
||||
|
||||
if (bgc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR))
|
||||
bgc->dir = bgc->read_reg(bgc->reg_dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bgpio_remove(struct bgpio_chip *bgc)
|
||||
{
|
||||
gpiochip_remove(&bgc->gc);
|
||||
free(bgc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIO_GENERIC_PLATFORM
|
||||
|
||||
static void __iomem *bgpio_map(struct device_d *dev, const char *name,
|
||||
resource_size_t sane_sz, int *err)
|
||||
{
|
||||
struct resource *r;
|
||||
void __iomem *ret;
|
||||
|
||||
*err = 0;
|
||||
|
||||
r = dev_get_resource_by_name(dev, name);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
if (resource_size(r) != sane_sz) {
|
||||
*err = -EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = request_iomem_region(dev_name(dev), r->start, r->end);
|
||||
if (!ret) {
|
||||
*err = -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bgpio_dev_probe(struct device_d *dev)
|
||||
{
|
||||
struct resource *r;
|
||||
void __iomem *dat;
|
||||
void __iomem *set;
|
||||
void __iomem *clr;
|
||||
void __iomem *dirout;
|
||||
void __iomem *dirin;
|
||||
unsigned int sz;
|
||||
unsigned long flags = 0;
|
||||
int err;
|
||||
struct bgpio_chip *bgc;
|
||||
struct bgpio_pdata *pdata = dev->platform_data;
|
||||
|
||||
r = dev_get_resource_by_name(dev, "dat");
|
||||
if (!r)
|
||||
return -EINVAL;
|
||||
|
||||
sz = resource_size(r);
|
||||
|
||||
dat = bgpio_map(dev, "dat", sz, &err);
|
||||
if (!dat)
|
||||
return err ? err : -EINVAL;
|
||||
|
||||
set = bgpio_map(dev, "set", sz, &err);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
clr = bgpio_map(dev, "clr", sz, &err);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dirout = bgpio_map(dev, "dirout", sz, &err);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dirin = bgpio_map(dev, "dirin", sz, &err);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dev_get_drvdata(dev, &flags);
|
||||
|
||||
bgc = xzalloc(sizeof(struct bgpio_chip));
|
||||
if (!bgc)
|
||||
return -ENOMEM;
|
||||
|
||||
err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, flags);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (pdata) {
|
||||
bgc->gc.base = pdata->base;
|
||||
if (pdata->ngpio > 0)
|
||||
bgc->gc.ngpio = pdata->ngpio;
|
||||
}
|
||||
|
||||
dev->priv = bgc;
|
||||
|
||||
return gpiochip_add(&bgc->gc);
|
||||
}
|
||||
|
||||
static void bgpio_dev_remove(struct device_d *dev)
|
||||
{
|
||||
struct bgpio_chip *bgc = dev->priv;
|
||||
|
||||
bgpio_remove(bgc);
|
||||
}
|
||||
|
||||
static struct platform_device_id bgpio_id_table[] = {
|
||||
{
|
||||
.name = "basic-mmio-gpio",
|
||||
.driver_data = 0,
|
||||
},
|
||||
{
|
||||
.name = "basic-mmio-gpio-be",
|
||||
.driver_data = BGPIOF_BIG_ENDIAN,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct driver_d bgpio_driver = {
|
||||
.name = "basic-mmio-gpio",
|
||||
.id_table = bgpio_id_table,
|
||||
.probe = bgpio_dev_probe,
|
||||
.remove = bgpio_dev_remove,
|
||||
};
|
||||
|
||||
static int bgpio_register(void)
|
||||
{
|
||||
return platform_driver_register(&bgpio_driver);
|
||||
}
|
||||
coredevice_initcall(bgpio_register);
|
||||
|
||||
#endif
|
||||
|
||||
MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
|
||||
MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -189,6 +189,11 @@ int gpiochip_add(struct gpio_chip *chip)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void gpiochip_remove(struct gpio_chip *chip)
|
||||
{
|
||||
list_del(&chip->list);
|
||||
}
|
||||
|
||||
int gpio_get_num(struct device_d *dev, int gpio)
|
||||
{
|
||||
struct gpio_chip *chip;
|
||||
|
|
|
@ -24,6 +24,11 @@ config MFD_STMPE
|
|||
depends on I2C
|
||||
bool "STMPE-i2c driver"
|
||||
|
||||
config MFD_SYSCON
|
||||
bool "System Controller Register"
|
||||
help
|
||||
Select this option to enable accessing system control registers
|
||||
|
||||
config MFD_TWLCORE
|
||||
bool
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ obj-$(CONFIG_MFD_MC34704) += mc34704.o
|
|||
obj-$(CONFIG_MFD_MC34708) += mc34708.o
|
||||
obj-$(CONFIG_MFD_MC9SDZ60) += mc9sdz60.o
|
||||
obj-$(CONFIG_MFD_STMPE) += stmpe-i2c.o
|
||||
obj-$(CONFIG_MFD_SYSCON) += syscon.o
|
||||
obj-$(CONFIG_MFD_TWLCORE) += twl-core.o
|
||||
obj-$(CONFIG_MFD_TWL4030) += twl4030.o
|
||||
obj-$(CONFIG_MFD_TWL6030) += twl6030.o
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* System Control Driver
|
||||
*
|
||||
* Based on linux driver by:
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro Ltd.
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <io.h>
|
||||
#include <init.h>
|
||||
#include <common.h>
|
||||
#include <driver.h>
|
||||
#include <malloc.h>
|
||||
#include <xfuncs.h>
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <mfd/syscon.h>
|
||||
|
||||
struct syscon {
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
void __iomem *syscon_base_lookup_by_pdevname(const char *s)
|
||||
{
|
||||
struct syscon *syscon;
|
||||
struct device_d *dev;
|
||||
|
||||
for_each_device(dev) {
|
||||
if (!strcmp(dev_name(dev), s)) {
|
||||
syscon = dev->priv;
|
||||
return syscon->base;
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static int syscon_probe(struct device_d *dev)
|
||||
{
|
||||
struct syscon *syscon;
|
||||
struct resource *res;
|
||||
|
||||
syscon = xzalloc(sizeof(struct syscon));
|
||||
if (!syscon)
|
||||
return -ENOMEM;
|
||||
|
||||
res = dev_get_resource(dev, 0);
|
||||
if (!res) {
|
||||
free(syscon);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
res = request_iomem_region(dev_name(dev), res->start, res->end);
|
||||
if (!res) {
|
||||
free(syscon);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
syscon->base = (void __iomem *)res->start;
|
||||
dev->priv = syscon;
|
||||
|
||||
dev_info(dev, "map 0x%x-0x%x registered\n", res->start, res->end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id syscon_ids[] = {
|
||||
{ "syscon", },
|
||||
#ifdef CONFIG_ARCH_CLPS711X
|
||||
{ "clps711x-syscon", },
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct driver_d syscon_driver = {
|
||||
.name = "syscon",
|
||||
.probe = syscon_probe,
|
||||
.id_table = syscon_ids,
|
||||
};
|
||||
|
||||
static int __init syscon_init(void)
|
||||
{
|
||||
return platform_driver_register(&syscon_driver);
|
||||
}
|
||||
core_initcall(syscon_init);
|
||||
|
||||
MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
|
||||
MODULE_DESCRIPTION("System Control driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -15,18 +15,21 @@
|
|||
#include <io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <mfd/syscon.h>
|
||||
|
||||
#include <mach/clps711x.h>
|
||||
|
||||
struct clps711x_uart {
|
||||
void __iomem *UBRLCR;
|
||||
void __iomem *SYSCON;
|
||||
void __iomem *SYSFLG;
|
||||
void __iomem *UARTDR;
|
||||
void __iomem *syscon;
|
||||
struct clk *uart_clk;
|
||||
struct console_device cdev;
|
||||
};
|
||||
|
||||
#define SYSCON(x) ((x)->syscon + 0x00)
|
||||
#define SYSFLG(x) ((x)->syscon + 0x40)
|
||||
|
||||
static int clps711x_setbaudrate(struct console_device *cdev, int baudrate)
|
||||
{
|
||||
struct clps711x_uart *s = cdev->dev->priv;
|
||||
|
@ -48,7 +51,7 @@ static void clps711x_init_port(struct console_device *cdev)
|
|||
u32 tmp;
|
||||
|
||||
/* Disable the UART */
|
||||
writel(readl(s->SYSCON) & ~SYSCON_UARTEN, s->SYSCON);
|
||||
writel(readl(SYSCON(s)) & ~SYSCON_UARTEN, SYSCON(s));
|
||||
|
||||
/* Setup Line Control Register */
|
||||
tmp = readl(s->UBRLCR) & UBRLCR_BAUD_MASK;
|
||||
|
@ -59,7 +62,7 @@ static void clps711x_init_port(struct console_device *cdev)
|
|||
clps711x_setbaudrate(cdev, CONFIG_BAUDRATE);
|
||||
|
||||
/* Enable the UART */
|
||||
writel(readl(s->SYSCON) | SYSCON_UARTEN, s->SYSCON);
|
||||
writel(readl(SYSCON(s)) | SYSCON_UARTEN, SYSCON(s));
|
||||
}
|
||||
|
||||
static void clps711x_putc(struct console_device *cdev, char c)
|
||||
|
@ -67,7 +70,7 @@ static void clps711x_putc(struct console_device *cdev, char c)
|
|||
struct clps711x_uart *s = cdev->dev->priv;
|
||||
|
||||
/* Wait until there is space in the FIFO */
|
||||
while (readl(s->SYSFLG) & SYSFLG_UTXFF)
|
||||
while (readl(SYSFLG(s)) & SYSFLG_UTXFF)
|
||||
barrier();
|
||||
|
||||
/* Send the character */
|
||||
|
@ -80,7 +83,7 @@ static int clps711x_getc(struct console_device *cdev)
|
|||
u16 data;
|
||||
|
||||
/* Wait until there is data in the FIFO */
|
||||
while (readl(s->SYSFLG) & SYSFLG_URXFE)
|
||||
while (readl(SYSFLG(s)) & SYSFLG_URXFE)
|
||||
barrier();
|
||||
|
||||
data = readw(s->UARTDR);
|
||||
|
@ -96,31 +99,35 @@ static int clps711x_tstc(struct console_device *cdev)
|
|||
{
|
||||
struct clps711x_uart *s = cdev->dev->priv;
|
||||
|
||||
return !(readl(s->SYSFLG) & SYSFLG_URXFE);
|
||||
return !(readl(SYSFLG(s)) & SYSFLG_URXFE);
|
||||
}
|
||||
|
||||
static void clps711x_flush(struct console_device *cdev)
|
||||
{
|
||||
struct clps711x_uart *s = cdev->dev->priv;
|
||||
|
||||
while (readl(s->SYSFLG) & SYSFLG_UBUSY)
|
||||
while (readl(SYSFLG(s)) & SYSFLG_UBUSY)
|
||||
barrier();
|
||||
}
|
||||
|
||||
static int clps711x_probe(struct device_d *dev)
|
||||
{
|
||||
struct clps711x_uart *s;
|
||||
char syscon_dev[18];
|
||||
|
||||
BUG_ON(dev->num_resources != 4);
|
||||
BUG_ON(dev->num_resources != 2);
|
||||
BUG_ON((dev->id != 0) && (dev->id != 1));
|
||||
|
||||
s = xzalloc(sizeof(struct clps711x_uart));
|
||||
s->uart_clk = clk_get(dev, NULL);
|
||||
BUG_ON(IS_ERR(s->uart_clk));
|
||||
|
||||
s->UBRLCR = dev_get_mem_region(dev, 0);
|
||||
s->SYSCON = dev_get_mem_region(dev, 1);
|
||||
s->SYSFLG = dev_get_mem_region(dev, 2);
|
||||
s->UARTDR = dev_get_mem_region(dev, 3);
|
||||
s->UARTDR = dev_get_mem_region(dev, 1);
|
||||
|
||||
sprintf(syscon_dev, "clps711x-syscon%i", dev->id + 1);
|
||||
s->syscon = syscon_base_lookup_by_pdevname(syscon_dev);
|
||||
BUG_ON(IS_ERR(s->syscon));
|
||||
|
||||
dev->priv = s;
|
||||
s->cdev.dev = dev;
|
||||
|
|
|
@ -40,6 +40,7 @@ struct gpio_chip {
|
|||
};
|
||||
|
||||
int gpiochip_add(struct gpio_chip *chip);
|
||||
void gpiochip_remove(struct gpio_chip *chip);
|
||||
|
||||
int gpio_get_num(struct device_d *dev, int gpio);
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Basic memory-mapped GPIO controllers.
|
||||
*
|
||||
* Based on linux driver by:
|
||||
* Copyright 2008 MontaVista Software, Inc.
|
||||
* Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __BASIC_MMIO_GPIO_H
|
||||
#define __BASIC_MMIO_GPIO_H
|
||||
|
||||
#include <common.h>
|
||||
#include <gpio.h>
|
||||
#include <io.h>
|
||||
|
||||
struct bgpio_pdata {
|
||||
int base;
|
||||
int ngpio;
|
||||
};
|
||||
|
||||
struct bgpio_chip {
|
||||
struct gpio_chip gc;
|
||||
struct gpio_ops ops;
|
||||
|
||||
unsigned int (*read_reg)(void __iomem *reg);
|
||||
void (*write_reg)(void __iomem *reg, unsigned int data);
|
||||
|
||||
void __iomem *reg_dat;
|
||||
void __iomem *reg_set;
|
||||
void __iomem *reg_clr;
|
||||
void __iomem *reg_dir;
|
||||
|
||||
/* Number of bits (GPIOs): <register width> * 8. */
|
||||
int bits;
|
||||
|
||||
/*
|
||||
* Some GPIO controllers work with the big-endian bits notation,
|
||||
* e.g. in a 8-bits register, GPIO7 is the least significant bit.
|
||||
*/
|
||||
unsigned int (*pin2mask)(struct bgpio_chip *bgc, unsigned int pin);
|
||||
|
||||
/* Shadowed data register to clear/set bits safely. */
|
||||
unsigned int data;
|
||||
|
||||
/* Shadowed direction registers to clear/set direction safely. */
|
||||
unsigned int dir;
|
||||
};
|
||||
|
||||
static inline struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc)
|
||||
{
|
||||
return container_of(gc, struct bgpio_chip, gc);
|
||||
}
|
||||
|
||||
int bgpio_init(struct bgpio_chip *bgc, struct device_d *dev,
|
||||
unsigned int sz, void __iomem *dat, void __iomem *set,
|
||||
void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
|
||||
unsigned long flags);
|
||||
void bgpio_remove(struct bgpio_chip *bgc);
|
||||
|
||||
#define BGPIOF_BIG_ENDIAN BIT(0)
|
||||
#define BGPIOF_UNREADABLE_REG_SET BIT(1) /* reg_set is unreadable */
|
||||
#define BGPIOF_UNREADABLE_REG_DIR BIT(2) /* reg_dir is unreadable */
|
||||
|
||||
#endif /* __BASIC_MMIO_GPIO_H */
|
|
@ -111,10 +111,25 @@ struct resource {
|
|||
/* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */
|
||||
#define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */
|
||||
|
||||
/* Helpers to define resources */
|
||||
#define DEFINE_RES_NAMED(_start, _size, _name, _flags) \
|
||||
{ \
|
||||
.start = (_start), \
|
||||
.end = (_start) + (_size) - 1, \
|
||||
.name = (_name), \
|
||||
.flags = (_flags), \
|
||||
}
|
||||
|
||||
#define DEFINE_RES_MEM_NAMED(_start, _size, _name) \
|
||||
DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_MEM)
|
||||
#define DEFINE_RES_MEM(_start, _size) \
|
||||
DEFINE_RES_MEM_NAMED((_start), (_size), NULL)
|
||||
|
||||
static inline resource_size_t resource_size(const struct resource *res)
|
||||
{
|
||||
return res->end - res->start + 1;
|
||||
}
|
||||
|
||||
static inline unsigned long resource_type(const struct resource *res)
|
||||
{
|
||||
return res->flags & IORESOURCE_TYPE_BITS;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* System Control Driver
|
||||
*
|
||||
* Based on linux driver by:
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro Ltd.
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __MFD_SYSCON_H__
|
||||
#define __MFD_SYSCON_H__
|
||||
|
||||
#ifdef CONFIG_MFD_SYSCON
|
||||
void __iomem *syscon_base_lookup_by_pdevname(const char *);
|
||||
#else
|
||||
static inline void __iomem *syscon_base_lookup_by_pdevname(const char *)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue